cpu.cc revision 8766
11689SN/A/* 22325SN/A * Copyright (c) 2004-2006 The Regents of The University of Michigan 31689SN/A * Copyright (c) 2011 Regents of the University of California 41689SN/A * All rights reserved. 51689SN/A * 61689SN/A * Redistribution and use in source and binary forms, with or without 71689SN/A * modification, are permitted provided that the following conditions are 81689SN/A * met: redistributions of source code must retain the above copyright 91689SN/A * notice, this list of conditions and the following disclaimer; 101689SN/A * redistributions in binary form must reproduce the above copyright 111689SN/A * notice, this list of conditions and the following disclaimer in the 121689SN/A * documentation and/or other materials provided with the distribution; 131689SN/A * neither the name of the copyright holders nor the names of its 141689SN/A * contributors may be used to endorse or promote products derived from 151689SN/A * this software without specific prior written permission. 161689SN/A * 171689SN/A * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 181689SN/A * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 191689SN/A * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 201689SN/A * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 211689SN/A * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 221689SN/A * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 231689SN/A * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 241689SN/A * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 251689SN/A * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 261689SN/A * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 272665Ssaidi@eecs.umich.edu * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 282665Ssaidi@eecs.umich.edu * 292756Sksewell@umich.edu * Authors: Kevin Lim 301689SN/A * Korey Sewell 311689SN/A * Rick Strong 321858SN/A */ 332733Sktlim@umich.edu 341858SN/A#include "config/full_system.hh" 351858SN/A#include "config/the_isa.hh" 361060SN/A#include "config/use_checker.hh" 371060SN/A#include "cpu/o3/cpu.hh" 381060SN/A#include "cpu/o3/isa_specific.hh" 391060SN/A#include "cpu/o3/thread_context.hh" 401060SN/A#include "cpu/activity.hh" 412325SN/A#include "cpu/simple_thread.hh" 422683Sktlim@umich.edu#include "cpu/thread_context.hh" 432680Sktlim@umich.edu#include "debug/Activity.hh" 442817Sksewell@umich.edu#include "debug/O3CPU.hh" 451717SN/A#include "debug/Quiesce.hh" 461060SN/A#include "enums/MemoryMode.hh" 472325SN/A#include "sim/core.hh" 482292SN/A#include "sim/stat_control.hh" 492292SN/A#include "sim/system.hh" 502794Sktlim@umich.edu 512794Sktlim@umich.edu#if FULL_SYSTEM 522794Sktlim@umich.edu#include "cpu/quiesce_event.hh" 532794Sktlim@umich.edu#else 541060SN/A#include "sim/process.hh" 552669Sktlim@umich.edu#endif 561060SN/A 572733Sktlim@umich.edu#if USE_CHECKER 582292SN/A#include "cpu/checker/cpu.hh" 591060SN/A#endif 601060SN/A 611060SN/A#if THE_ISA == ALPHA_ISA 622292SN/A#include "arch/alpha/osfpal.hh" 632733Sktlim@umich.edu#include "debug/Activity.hh" 642292SN/A#endif 652292SN/A 662292SN/Aclass BaseCPUParams; 672292SN/A 681060SN/Ausing namespace TheISA; 691755SN/Ausing namespace std; 701060SN/A 711060SN/ABaseO3CPU::BaseO3CPU(BaseCPUParams *params) 721060SN/A : BaseCPU(params) 731060SN/A{ 741060SN/A} 751060SN/A 761755SN/Avoid 771060SN/ABaseO3CPU::regStats() 781060SN/A{ 791060SN/A BaseCPU::regStats(); 801060SN/A} 811060SN/A 821060SN/Atemplate <class Impl> 831755SN/AFullO3CPU<Impl>::TickEvent::TickEvent(FullO3CPU<Impl> *c) 841060SN/A : Event(CPU_Tick_Pri), cpu(c) 851755SN/A{ 861060SN/A} 871060SN/A 881060SN/Atemplate <class Impl> 892829Sksewell@umich.eduvoid 902829Sksewell@umich.eduFullO3CPU<Impl>::TickEvent::process() 912829Sksewell@umich.edu{ 922829Sksewell@umich.edu cpu->tick(); 932829Sksewell@umich.edu} 942829Sksewell@umich.edu 952829Sksewell@umich.edutemplate <class Impl> 962829Sksewell@umich.educonst char * 972829Sksewell@umich.eduFullO3CPU<Impl>::TickEvent::description() const 982829Sksewell@umich.edu{ 992829Sksewell@umich.edu return "FullO3CPU tick"; 1002829Sksewell@umich.edu} 1012829Sksewell@umich.edu 1022829Sksewell@umich.edutemplate <class Impl> 1032829Sksewell@umich.eduFullO3CPU<Impl>::ActivateThreadEvent::ActivateThreadEvent() 1042829Sksewell@umich.edu : Event(CPU_Switch_Pri) 1052829Sksewell@umich.edu{ 1062829Sksewell@umich.edu} 1072829Sksewell@umich.edu 1082829Sksewell@umich.edutemplate <class Impl> 1092829Sksewell@umich.eduvoid 1102829Sksewell@umich.eduFullO3CPU<Impl>::ActivateThreadEvent::init(int thread_num, 1112829Sksewell@umich.edu FullO3CPU<Impl> *thread_cpu) 1122829Sksewell@umich.edu{ 1132829Sksewell@umich.edu tid = thread_num; 1142829Sksewell@umich.edu cpu = thread_cpu; 1152829Sksewell@umich.edu} 1162829Sksewell@umich.edu 1172829Sksewell@umich.edutemplate <class Impl> 1182875Sksewell@umich.eduvoid 1192875Sksewell@umich.eduFullO3CPU<Impl>::ActivateThreadEvent::process() 1202875Sksewell@umich.edu{ 1212875Sksewell@umich.edu cpu->activateThread(tid); 1222875Sksewell@umich.edu} 1232875Sksewell@umich.edu 1242875Sksewell@umich.edutemplate <class Impl> 1252875Sksewell@umich.educonst char * 1262875Sksewell@umich.eduFullO3CPU<Impl>::ActivateThreadEvent::description() const 1272875Sksewell@umich.edu{ 1282875Sksewell@umich.edu return "FullO3CPU \"Activate Thread\""; 1292875Sksewell@umich.edu} 1302875Sksewell@umich.edu 1312875Sksewell@umich.edutemplate <class Impl> 1322875Sksewell@umich.eduFullO3CPU<Impl>::DeallocateContextEvent::DeallocateContextEvent() 1332875Sksewell@umich.edu : Event(CPU_Tick_Pri), tid(0), remove(false), cpu(NULL) 1342875Sksewell@umich.edu{ 1352875Sksewell@umich.edu} 1362875Sksewell@umich.edu 1372875Sksewell@umich.edutemplate <class Impl> 1382875Sksewell@umich.eduvoid 1392875Sksewell@umich.eduFullO3CPU<Impl>::DeallocateContextEvent::init(int thread_num, 1402875Sksewell@umich.edu FullO3CPU<Impl> *thread_cpu) 1412875Sksewell@umich.edu{ 1422875Sksewell@umich.edu tid = thread_num; 1432875Sksewell@umich.edu cpu = thread_cpu; 1442875Sksewell@umich.edu remove = false; 1452875Sksewell@umich.edu} 1462875Sksewell@umich.edu 1472875Sksewell@umich.edutemplate <class Impl> 1482292SN/Avoid 1492733Sktlim@umich.eduFullO3CPU<Impl>::DeallocateContextEvent::process() 1501060SN/A{ 1512292SN/A cpu->deactivateThread(tid); 1521060SN/A if (remove) 1531060SN/A cpu->removeThread(tid); 1541060SN/A} 1551060SN/A 1561060SN/Atemplate <class Impl> 1571060SN/Aconst char * 1582292SN/AFullO3CPU<Impl>::DeallocateContextEvent::description() const 1591060SN/A{ 1602831Sksewell@umich.edu return "FullO3CPU \"Deallocate Context\""; 1612292SN/A} 1622292SN/A 1631060SN/Atemplate <class Impl> 1642292SN/AFullO3CPU<Impl>::FullO3CPU(DerivO3CPUParams *params) 1652292SN/A : BaseO3CPU(params), 1662292SN/A itb(params->itb), 1671060SN/A dtb(params->dtb), 1682831Sksewell@umich.edu tickEvent(this), 1692292SN/A#ifndef NDEBUG 1702292SN/A instcount(0), 1712292SN/A#endif 1722292SN/A removeInstsThisCycle(false), 1731060SN/A fetch(this, params), 1742873Sktlim@umich.edu decode(this, params), 1752873Sktlim@umich.edu rename(this, params), 1762873Sktlim@umich.edu iew(this, params), 1772873Sktlim@umich.edu commit(this, params), 1782873Sktlim@umich.edu 1792873Sktlim@umich.edu regFile(this, params->numPhysIntRegs, 1802873Sktlim@umich.edu params->numPhysFloatRegs), 1812873Sktlim@umich.edu 1821060SN/A freeList(params->numThreads, 1831060SN/A TheISA::NumIntRegs, params->numPhysIntRegs, 1841060SN/A TheISA::NumFloatRegs, params->numPhysFloatRegs), 1851858SN/A 1862292SN/A rob(this, 1871060SN/A params->numROBEntries, params->squashWidth, 1881060SN/A params->smtROBPolicy, params->smtROBThreshold, 1892292SN/A params->numThreads), 1902843Sktlim@umich.edu 1912316SN/A scoreboard(params->numThreads, 1922316SN/A TheISA::NumIntRegs, params->numPhysIntRegs, 1931060SN/A TheISA::NumFloatRegs, params->numPhysFloatRegs, 1941060SN/A TheISA::NumMiscRegs * numThreads, 1951681SN/A TheISA::ZeroReg), 1962733Sktlim@umich.edu 1972733Sktlim@umich.edu timeBuffer(params->backComSize, params->forwardComSize), 1982794Sktlim@umich.edu fetchQueue(params->backComSize, params->forwardComSize), 1992733Sktlim@umich.edu decodeQueue(params->backComSize, params->forwardComSize), 2002316SN/A renameQueue(params->backComSize, params->forwardComSize), 2012316SN/A iewQueue(params->backComSize, params->forwardComSize), 2022316SN/A activityRec(name(), NumStages, 2032316SN/A params->backComSize + params->forwardComSize, 2042316SN/A params->activity), 2052316SN/A 2062794Sktlim@umich.edu globalSeqNum(1), 2072794Sktlim@umich.edu system(params->system), 2082794Sktlim@umich.edu drainCount(0), 2092316SN/A deferRegistration(params->defer_registration) 2102316SN/A{ 2111858SN/A if (!deferRegistration) { 2122292SN/A _status = Running; 2132292SN/A } else { 2141681SN/A _status = Idle; 2151681SN/A } 2162325SN/A 2172325SN/A#if USE_CHECKER 2182325SN/A if (params->checker) { 2191060SN/A BaseCPU *temp_checker = params->checker; 2202292SN/A checker = dynamic_cast<Checker<DynInstPtr> *>(temp_checker); 2212292SN/A#if FULL_SYSTEM 2222292SN/A checker->setSystem(params->system); 2232292SN/A#endif 2242292SN/A } else { 2252292SN/A checker = NULL; 2261060SN/A } 2271060SN/A#endif // USE_CHECKER 2281060SN/A 2291060SN/A#if !FULL_SYSTEM 2301060SN/A thread.resize(numThreads); 2311060SN/A tids.resize(numThreads); 2321060SN/A#endif 2331060SN/A 2341060SN/A // The stages also need their CPU pointer setup. However this 2351060SN/A // must be done at the upper level CPU because they have pointers 2361060SN/A // to the upper level CPU, and not this FullO3CPU. 2372292SN/A 2381060SN/A // Set up Pointers to the activeThreads list for each stage 2391060SN/A fetch.setActiveThreads(&activeThreads); 2401060SN/A decode.setActiveThreads(&activeThreads); 2411060SN/A rename.setActiveThreads(&activeThreads); 2421060SN/A iew.setActiveThreads(&activeThreads); 2431060SN/A commit.setActiveThreads(&activeThreads); 2441060SN/A 2451060SN/A // Give each of the stages the time buffer they will use. 2462292SN/A fetch.setTimeBuffer(&timeBuffer); 2472292SN/A decode.setTimeBuffer(&timeBuffer); 2482292SN/A rename.setTimeBuffer(&timeBuffer); 2492292SN/A iew.setTimeBuffer(&timeBuffer); 2502292SN/A commit.setTimeBuffer(&timeBuffer); 2512307SN/A 2522831Sksewell@umich.edu // Also setup each of the stages' queues. 2532831Sksewell@umich.edu fetch.setFetchQueue(&fetchQueue); 2542831Sksewell@umich.edu decode.setFetchQueue(&fetchQueue); 2552831Sksewell@umich.edu commit.setFetchQueue(&fetchQueue); 2562831Sksewell@umich.edu decode.setDecodeQueue(&decodeQueue); 2572831Sksewell@umich.edu rename.setDecodeQueue(&decodeQueue); 2582292SN/A rename.setRenameQueue(&renameQueue); 2592307SN/A iew.setRenameQueue(&renameQueue); 2602292SN/A iew.setIEWQueue(&iewQueue); 2612292SN/A commit.setIEWQueue(&iewQueue); 2622316SN/A commit.setRenameQueue(&renameQueue); 2632292SN/A 2642292SN/A commit.setIEWStage(&iew); 2652292SN/A rename.setIEWStage(&iew); 2662292SN/A rename.setCommitStage(&commit); 2672292SN/A 2682292SN/A#if !FULL_SYSTEM 2691060SN/A ThreadID active_threads = params->workload.size(); 2702292SN/A 2712292SN/A if (active_threads > Impl::MaxThreads) { 2721060SN/A panic("Workload Size too large. Increase the 'MaxThreads'" 2732292SN/A "constant in your O3CPU impl. file (e.g. o3/alpha/impl.hh) or " 2742307SN/A "edit your workload size."); 2752292SN/A } 2762292SN/A#else 2772292SN/A ThreadID active_threads = 1; 2782325SN/A#endif 2792292SN/A 2802292SN/A //Make Sure That this a Valid Architeture 2812292SN/A assert(params->numPhysIntRegs >= numThreads * TheISA::NumIntRegs); 2822325SN/A assert(params->numPhysFloatRegs >= numThreads * TheISA::NumFloatRegs); 2832292SN/A 2842292SN/A rename.setScoreboard(&scoreboard); 2852292SN/A iew.setScoreboard(&scoreboard); 2862292SN/A 2872292SN/A // Setup the rename map for whichever stages need it. 2882292SN/A PhysRegIndex lreg_idx = 0; 2892292SN/A PhysRegIndex freg_idx = params->numPhysIntRegs; //Index to 1 after int regs 2902292SN/A 2912292SN/A for (ThreadID tid = 0; tid < numThreads; tid++) { 2922292SN/A bool bindRegs = (tid <= active_threads - 1); 2932292SN/A 2942325SN/A commitRenameMap[tid].init(TheISA::NumIntRegs, 2952292SN/A params->numPhysIntRegs, 2962292SN/A lreg_idx, //Index for Logical. Regs 2972292SN/A 2982325SN/A TheISA::NumFloatRegs, 2992292SN/A params->numPhysFloatRegs, 3002292SN/A freg_idx, //Index for Float Regs 3012292SN/A 3022292SN/A TheISA::NumMiscRegs, 3032292SN/A 3042292SN/A TheISA::ZeroReg, 3052292SN/A TheISA::ZeroReg, 3062292SN/A 3072292SN/A tid, 3082292SN/A false); 3092292SN/A 3102292SN/A renameMap[tid].init(TheISA::NumIntRegs, 3112292SN/A params->numPhysIntRegs, 3122292SN/A lreg_idx, //Index for Logical. Regs 3132292SN/A 3142292SN/A TheISA::NumFloatRegs, 3152292SN/A params->numPhysFloatRegs, 3161060SN/A freg_idx, //Index for Float Regs 3172292SN/A 3181060SN/A TheISA::NumMiscRegs, 3191060SN/A 3202292SN/A TheISA::ZeroReg, 3212292SN/A TheISA::ZeroReg, 3222292SN/A 3232829Sksewell@umich.edu tid, 3242829Sksewell@umich.edu bindRegs); 3252292SN/A 3261060SN/A activateThreadEvent[tid].init(tid, this); 3271060SN/A deallocateContextEvent[tid].init(tid, this); 3281060SN/A } 3291755SN/A 3301060SN/A rename.setRenameMap(renameMap); 3311060SN/A commit.setRenameMap(commitRenameMap); 3321060SN/A 3331060SN/A // Give renameMap & rename stage access to the freeList; 3341060SN/A for (ThreadID tid = 0; tid < numThreads; tid++) 3351755SN/A renameMap[tid].setFreeList(&freeList); 3361062SN/A rename.setFreeList(&freeList); 3372733Sktlim@umich.edu 3382292SN/A // Setup the ROB for whichever stages need it. 3392733Sktlim@umich.edu commit.setROB(&rob); 3402292SN/A 3412292SN/A lastRunningCycle = curTick(); 3422292SN/A 3432292SN/A lastActivatedCycle = -1; 3442292SN/A#if 0 3452292SN/A // Give renameMap & rename stage access to the freeList; 3462292SN/A for (ThreadID tid = 0; tid < numThreads; tid++) 3472292SN/A globalSeqNum[tid] = 1; 3482292SN/A#endif 3492292SN/A 3502292SN/A contextSwitch = false; 3512292SN/A DPRINTF(O3CPU, "Creating O3CPU object.\n"); 3522292SN/A 3532292SN/A // Setup any thread state. 3542292SN/A this->thread.resize(this->numThreads); 3552292SN/A 3562292SN/A for (ThreadID tid = 0; tid < this->numThreads; ++tid) { 3572292SN/A#if FULL_SYSTEM 3582292SN/A // SMT is not supported in FS mode yet. 3592292SN/A assert(this->numThreads == 1); 3602292SN/A this->thread[tid] = new Thread(this, 0, NULL); 3612292SN/A#else 3622292SN/A if (tid < params->workload.size()) { 3632292SN/A DPRINTF(O3CPU, "Workload[%i] process is %#x", 3642292SN/A tid, this->thread[tid]); 3652292SN/A this->thread[tid] = new typename FullO3CPU<Impl>::Thread( 3662292SN/A (typename Impl::O3CPU *)(this), 3672292SN/A tid, params->workload[tid]); 3682292SN/A 3692292SN/A //usedTids[tid] = true; 3702292SN/A //threadMap[tid] = tid; 3712292SN/A } else { 3722292SN/A //Allocate Empty thread so M5 can use later 3732292SN/A //when scheduling threads to CPU 3742292SN/A Process* dummy_proc = NULL; 3752292SN/A 3762292SN/A this->thread[tid] = new typename FullO3CPU<Impl>::Thread( 3772292SN/A (typename Impl::O3CPU *)(this), 3782292SN/A tid, dummy_proc); 3792292SN/A //usedTids[tid] = false; 3802292SN/A } 3812292SN/A#endif // !FULL_SYSTEM 3822292SN/A 3832292SN/A ThreadContext *tc; 3842292SN/A 3852292SN/A // Setup the TC that will serve as the interface to the threads/CPU. 3862292SN/A O3ThreadContext<Impl> *o3_tc = new O3ThreadContext<Impl>; 3872292SN/A 3882292SN/A tc = o3_tc; 3891062SN/A 3901062SN/A // If we're using a checker, then the TC should be the 3911062SN/A // CheckerThreadContext. 3922871Sktlim@umich.edu#if USE_CHECKER 3932871Sktlim@umich.edu if (params->checker) { 3942871Sktlim@umich.edu tc = new CheckerThreadContext<O3ThreadContext<Impl> >( 3952871Sktlim@umich.edu o3_tc, this->checker); 3962871Sktlim@umich.edu } 3972871Sktlim@umich.edu#endif 3982871Sktlim@umich.edu 3992871Sktlim@umich.edu o3_tc->cpu = (typename Impl::O3CPU *)(this); 4002871Sktlim@umich.edu assert(o3_tc->cpu); 4012871Sktlim@umich.edu o3_tc->thread = this->thread[tid]; 4022871Sktlim@umich.edu 4032871Sktlim@umich.edu#if FULL_SYSTEM 4041062SN/A // Setup quiesce event. 4051755SN/A this->thread[tid]->quiesceEvent = new EndQuiesceEvent(tc); 4061060SN/A#endif 4072733Sktlim@umich.edu // Give the thread the TC. 4081060SN/A this->thread[tid]->tc = tc; 4092292SN/A 4102292SN/A // Add the TC to the CPU's list of TC's. 4112325SN/A this->threadContexts.push_back(tc); 4122292SN/A } 4132292SN/A 4141060SN/A for (ThreadID tid = 0; tid < this->numThreads; tid++) 4151060SN/A this->thread[tid]->setFuncExeInst(0); 4161060SN/A 4171060SN/A lockAddr = 0; 4181060SN/A lockFlag = false; 4191060SN/A} 4201060SN/A 4211060SN/Atemplate <class Impl> 4221060SN/AFullO3CPU<Impl>::~FullO3CPU() 4231060SN/A{ 4242292SN/A} 4252292SN/A 4262292SN/Atemplate <class Impl> 4272292SN/Avoid 4282292SN/AFullO3CPU<Impl>::regStats() 4291060SN/A{ 4301060SN/A BaseO3CPU::regStats(); 4311060SN/A 4321060SN/A // Register any of the O3CPU's stats here. 4331060SN/A timesIdled 4341060SN/A .name(name() + ".timesIdled") 4351060SN/A .desc("Number of times that the entire CPU went into an idle state and" 4362325SN/A " unscheduled itself") 4372292SN/A .prereq(timesIdled); 4382292SN/A 4392292SN/A idleCycles 4402292SN/A .name(name() + ".idleCycles") 4412292SN/A .desc("Total number of cycles that the CPU has spent unscheduled due " 4422325SN/A "to idling") 4432867Sktlim@umich.edu .prereq(idleCycles); 4442905Sktlim@umich.edu 4452325SN/A // Number of Instructions simulated 4462325SN/A // -------------------------------- 4472325SN/A // Should probably be in Base CPU but need templated 4482325SN/A // MaxThreads so put in here instead 4492325SN/A committedInsts 4502325SN/A .init(numThreads) 4512325SN/A .name(name() + ".committedInsts") 4522325SN/A .desc("Number of Instructions Simulated"); 4532292SN/A 4542292SN/A totalCommittedInsts 4552292SN/A .name(name() + ".committedInsts_total") 4562292SN/A .desc("Number of Instructions Simulated"); 4572292SN/A 4582292SN/A cpi 4591060SN/A .name(name() + ".cpi") 4601060SN/A .desc("CPI: Cycles Per Instruction") 4611060SN/A .precision(6); 4621060SN/A cpi = numCycles / committedInsts; 4631755SN/A 4641060SN/A totalCpi 4652307SN/A .name(name() + ".cpi_total") 4662680Sktlim@umich.edu .desc("CPI: Total CPI of All Threads") 4672292SN/A .precision(6); 4681060SN/A totalCpi = numCycles / totalCommittedInsts; 4692292SN/A 4702292SN/A ipc 4712292SN/A .name(name() + ".ipc") 4722292SN/A .desc("IPC: Instructions Per Cycle") 4732292SN/A .precision(6); 4742292SN/A ipc = committedInsts / numCycles; 4751858SN/A 4762680Sktlim@umich.edu totalIpc 4771681SN/A .name(name() + ".ipc_total") 4782680Sktlim@umich.edu .desc("IPC: Total IPC of All Threads") 4791681SN/A .precision(6); 4802292SN/A totalIpc = totalCommittedInsts / numCycles; 4812680Sktlim@umich.edu 4822292SN/A this->fetch.regStats(); 4831060SN/A this->decode.regStats(); 4841060SN/A this->rename.regStats(); 4852292SN/A this->iew.regStats(); 4862680Sktlim@umich.edu this->commit.regStats(); 4872292SN/A this->rob.regStats(); 4882292SN/A 4892292SN/A intRegfileReads 4902292SN/A .name(name() + ".int_regfile_reads") 4912292SN/A .desc("number of integer regfile reads") 4922292SN/A .prereq(intRegfileReads); 4932292SN/A 4942316SN/A intRegfileWrites 4952292SN/A .name(name() + ".int_regfile_writes") 4962292SN/A .desc("number of integer regfile writes") 4972292SN/A .prereq(intRegfileWrites); 4982292SN/A 4992292SN/A fpRegfileReads 5002292SN/A .name(name() + ".fp_regfile_reads") 5012292SN/A .desc("number of floating regfile reads") 5022292SN/A .prereq(fpRegfileReads); 5032292SN/A 5042292SN/A fpRegfileWrites 5052875Sksewell@umich.edu .name(name() + ".fp_regfile_writes") 5062875Sksewell@umich.edu .desc("number of floating regfile writes") 5072875Sksewell@umich.edu .prereq(fpRegfileWrites); 5082875Sksewell@umich.edu 5092875Sksewell@umich.edu miscRegfileReads 5102875Sksewell@umich.edu .name(name() + ".misc_regfile_reads") 5112875Sksewell@umich.edu .desc("number of misc regfile reads") 5122875Sksewell@umich.edu .prereq(miscRegfileReads); 5132875Sksewell@umich.edu 5142875Sksewell@umich.edu miscRegfileWrites 5152875Sksewell@umich.edu .name(name() + ".misc_regfile_writes") 5162875Sksewell@umich.edu .desc("number of misc regfile writes") 5172875Sksewell@umich.edu .prereq(miscRegfileWrites); 5182875Sksewell@umich.edu} 5192875Sksewell@umich.edu 5202875Sksewell@umich.edutemplate <class Impl> 5212875Sksewell@umich.eduPort * 5222875Sksewell@umich.eduFullO3CPU<Impl>::getPort(const std::string &if_name, int idx) 5232875Sksewell@umich.edu{ 5242875Sksewell@umich.edu if (if_name == "dcache_port") 5252875Sksewell@umich.edu return iew.getDcachePort(); 5262875Sksewell@umich.edu else if (if_name == "icache_port") 5272875Sksewell@umich.edu return fetch.getIcachePort(); 5282875Sksewell@umich.edu else 5292875Sksewell@umich.edu panic("No Such Port\n"); 5302875Sksewell@umich.edu} 5312875Sksewell@umich.edu 5322875Sksewell@umich.edutemplate <class Impl> 5332875Sksewell@umich.eduvoid 5342875Sksewell@umich.eduFullO3CPU<Impl>::tick() 5352875Sksewell@umich.edu{ 5362875Sksewell@umich.edu DPRINTF(O3CPU, "\n\nFullO3CPU: Ticking main, FullO3CPU.\n"); 5372875Sksewell@umich.edu 5382875Sksewell@umich.edu ++numCycles; 5392875Sksewell@umich.edu 5402875Sksewell@umich.edu// activity = false; 5412875Sksewell@umich.edu 5422875Sksewell@umich.edu //Tick each of the stages 5432875Sksewell@umich.edu fetch.tick(); 5442875Sksewell@umich.edu 5452875Sksewell@umich.edu decode.tick(); 5462875Sksewell@umich.edu 5472875Sksewell@umich.edu rename.tick(); 5482875Sksewell@umich.edu 5492875Sksewell@umich.edu iew.tick(); 5502875Sksewell@umich.edu 5512875Sksewell@umich.edu commit.tick(); 5522875Sksewell@umich.edu 5532875Sksewell@umich.edu#if !FULL_SYSTEM 5542875Sksewell@umich.edu doContextSwitch(); 5552875Sksewell@umich.edu#endif 5562875Sksewell@umich.edu 5572875Sksewell@umich.edu // Now advance the time buffers 5582875Sksewell@umich.edu timeBuffer.advance(); 5592875Sksewell@umich.edu 5602875Sksewell@umich.edu fetchQueue.advance(); 5612875Sksewell@umich.edu decodeQueue.advance(); 5622875Sksewell@umich.edu renameQueue.advance(); 5632875Sksewell@umich.edu iewQueue.advance(); 5642875Sksewell@umich.edu 5652875Sksewell@umich.edu activityRec.advance(); 5662875Sksewell@umich.edu 5672875Sksewell@umich.edu if (removeInstsThisCycle) { 5682875Sksewell@umich.edu cleanUpRemovedInsts(); 5692875Sksewell@umich.edu } 5702875Sksewell@umich.edu 5712875Sksewell@umich.edu if (!tickEvent.scheduled()) { 5722875Sksewell@umich.edu if (_status == SwitchedOut || 5732875Sksewell@umich.edu getState() == SimObject::Drained) { 5742875Sksewell@umich.edu DPRINTF(O3CPU, "Switched out!\n"); 5752875Sksewell@umich.edu // increment stat 5762875Sksewell@umich.edu lastRunningCycle = curTick(); 5772875Sksewell@umich.edu } else if (!activityRec.active() || _status == Idle) { 5782875Sksewell@umich.edu DPRINTF(O3CPU, "Idle!\n"); 5792875Sksewell@umich.edu lastRunningCycle = curTick(); 5802911Sksewell@umich.edu timesIdled++; 5812910Sksewell@umich.edu } else { 5822910Sksewell@umich.edu schedule(tickEvent, nextCycle(curTick() + ticks(1))); 5832875Sksewell@umich.edu DPRINTF(O3CPU, "Scheduling next tick!\n"); 5842875Sksewell@umich.edu } 5852875Sksewell@umich.edu } 5862875Sksewell@umich.edu 5872875Sksewell@umich.edu#if !FULL_SYSTEM 5882875Sksewell@umich.edu updateThreadPriority(); 5892875Sksewell@umich.edu#endif 5902910Sksewell@umich.edu} 5912910Sksewell@umich.edu 5922910Sksewell@umich.edutemplate <class Impl> 5932875Sksewell@umich.eduvoid 5942875Sksewell@umich.eduFullO3CPU<Impl>::init() 5952875Sksewell@umich.edu{ 5962875Sksewell@umich.edu BaseCPU::init(); 5972292SN/A 5982292SN/A // Set inSyscall so that the CPU doesn't squash when initially 5992847Sksewell@umich.edu // setting up registers. 6002292SN/A for (ThreadID tid = 0; tid < numThreads; ++tid) 6012683Sktlim@umich.edu thread[tid]->inSyscall = true; 6022292SN/A 6032680Sktlim@umich.edu#if FULL_SYSTEM 6042292SN/A for (ThreadID tid = 0; tid < numThreads; tid++) { 6052847Sksewell@umich.edu ThreadContext *src_tc = threadContexts[tid]; 6062292SN/A TheISA::initCPU(src_tc, src_tc->contextId()); 6072292SN/A } 6082292SN/A#endif 6092292SN/A 6102292SN/A // Clear inSyscall. 6112292SN/A for (int tid = 0; tid < numThreads; ++tid) 6122292SN/A thread[tid]->inSyscall = false; 6132292SN/A 6142292SN/A // Initialize stages. 6152292SN/A fetch.initStage(); 6162292SN/A iew.initStage(); 6172292SN/A rename.initStage(); 6182292SN/A commit.initStage(); 6192292SN/A 6202292SN/A commit.setThreads(thread); 6212292SN/A} 6222292SN/A 6232292SN/Atemplate <class Impl> 6242292SN/Avoid 6252847Sksewell@umich.eduFullO3CPU<Impl>::activateThread(ThreadID tid) 6262292SN/A{ 6272847Sksewell@umich.edu list<ThreadID>::iterator isActive = 6282847Sksewell@umich.edu std::find(activeThreads.begin(), activeThreads.end(), tid); 6292847Sksewell@umich.edu 6302847Sksewell@umich.edu DPRINTF(O3CPU, "[tid:%i]: Calling activate thread.\n", tid); 6312847Sksewell@umich.edu 6322847Sksewell@umich.edu if (isActive == activeThreads.end()) { 6332292SN/A DPRINTF(O3CPU, "[tid:%i]: Adding to active threads list\n", 6342680Sktlim@umich.edu tid); 6352292SN/A 6362292SN/A activeThreads.push_back(tid); 6372292SN/A } 6382292SN/A} 6392292SN/A 6402292SN/Atemplate <class Impl> 6412292SN/Avoid 6422292SN/AFullO3CPU<Impl>::deactivateThread(ThreadID tid) 6432292SN/A{ 6442292SN/A //Remove From Active List, if Active 6452292SN/A list<ThreadID>::iterator thread_it = 6462292SN/A std::find(activeThreads.begin(), activeThreads.end(), tid); 6472877Sksewell@umich.edu 6482847Sksewell@umich.edu DPRINTF(O3CPU, "[tid:%i]: Calling deactivate thread.\n", tid); 6492847Sksewell@umich.edu 6502847Sksewell@umich.edu if (thread_it != activeThreads.end()) { 6512847Sksewell@umich.edu DPRINTF(O3CPU,"[tid:%i]: Removing from active threads list\n", 6522847Sksewell@umich.edu tid); 6532847Sksewell@umich.edu activeThreads.erase(thread_it); 6542292SN/A } 6552292SN/A} 6562292SN/A 6572292SN/Atemplate <class Impl> 6582292SN/ACounter 6592292SN/AFullO3CPU<Impl>::totalInstructions() const 6602292SN/A{ 6612847Sksewell@umich.edu Counter total(0); 6622292SN/A 6632292SN/A ThreadID size = thread.size(); 6642292SN/A for (ThreadID i = 0; i < size; i++) 6652292SN/A total += thread[i]->numInst; 6662292SN/A 6672292SN/A return total; 6682292SN/A} 6692847Sksewell@umich.edu 6702292SN/Atemplate <class Impl> 6712292SN/Avoid 6722292SN/AFullO3CPU<Impl>::activateContext(ThreadID tid, int delay) 6732875Sksewell@umich.edu{ 6742875Sksewell@umich.edu // Needs to set each stage to running as well. 6752292SN/A if (delay){ 6762292SN/A DPRINTF(O3CPU, "[tid:%i]: Scheduling thread context to activate " 6772292SN/A "on cycle %d\n", tid, curTick() + ticks(delay)); 6782847Sksewell@umich.edu scheduleActivateThreadEvent(tid, delay); 6792292SN/A } else { 6802292SN/A activateThread(tid); 6812292SN/A } 6822292SN/A 6832292SN/A if (lastActivatedCycle < curTick()) { 6842292SN/A scheduleTickEvent(delay); 6852292SN/A 6862292SN/A // Be sure to signal that there's some activity so the CPU doesn't 6872292SN/A // deschedule itself. 6882292SN/A activityRec.activity(); 6892292SN/A fetch.wakeFromQuiesce(); 6902733Sktlim@umich.edu 6912292SN/A lastActivatedCycle = curTick(); 6922292SN/A 6932292SN/A _status = Running; 6942292SN/A } 6952292SN/A} 6962292SN/A 6972733Sktlim@umich.edutemplate <class Impl> 6982292SN/Abool 6992292SN/AFullO3CPU<Impl>::deallocateContext(ThreadID tid, bool remove, int delay) 7002292SN/A{ 7012292SN/A // Schedule removal of thread data from CPU 7022733Sktlim@umich.edu if (delay){ 7032292SN/A DPRINTF(O3CPU, "[tid:%i]: Scheduling thread context to deallocate " 7042292SN/A "on cycle %d\n", tid, curTick() + ticks(delay)); 7052292SN/A scheduleDeallocateContextEvent(tid, remove, delay); 7062292SN/A return false; 7072292SN/A } else { 7082733Sktlim@umich.edu deactivateThread(tid); 7092292SN/A if (remove) 7102292SN/A removeThread(tid); 7112292SN/A return true; 7122292SN/A } 7132292SN/A} 7142733Sktlim@umich.edu 7152292SN/Atemplate <class Impl> 7162292SN/Avoid 7172292SN/AFullO3CPU<Impl>::suspendContext(ThreadID tid) 7182292SN/A{ 7192292SN/A DPRINTF(O3CPU,"[tid: %i]: Suspending Thread Context.\n", tid); 7202733Sktlim@umich.edu bool deallocated = deallocateContext(tid, false, 1); 7212292SN/A // If this was the last thread then unschedule the tick event. 7222292SN/A if ((activeThreads.size() == 1 && !deallocated) || 7232292SN/A activeThreads.size() == 0) 7242292SN/A unscheduleTickEvent(); 7252292SN/A _status = Idle; 7262292SN/A} 7272292SN/A 7282292SN/Atemplate <class Impl> 7292292SN/Avoid 7302292SN/AFullO3CPU<Impl>::haltContext(ThreadID tid) 7312292SN/A{ 7322292SN/A //For now, this is the same as deallocate 7332292SN/A DPRINTF(O3CPU,"[tid:%i]: Halt Context called. Deallocating", tid); 7342292SN/A deallocateContext(tid, true, 1); 7352292SN/A} 7362292SN/A 7372292SN/Atemplate <class Impl> 7382875Sksewell@umich.eduvoid 7392292SN/AFullO3CPU<Impl>::insertThread(ThreadID tid) 7402292SN/A{ 7411060SN/A DPRINTF(O3CPU,"[tid:%i] Initializing thread into CPU"); 7421060SN/A // Will change now that the PC and thread state is internal to the CPU 7431060SN/A // and not in the ThreadContext. 7441060SN/A#if FULL_SYSTEM 7452852Sktlim@umich.edu ThreadContext *src_tc = system->threadContexts[tid]; 7462864Sktlim@umich.edu#else 7472864Sktlim@umich.edu ThreadContext *src_tc = tcBase(tid); 7482864Sktlim@umich.edu#endif 7492864Sktlim@umich.edu 7502864Sktlim@umich.edu //Bind Int Regs to Rename Map 7512864Sktlim@umich.edu for (int ireg = 0; ireg < TheISA::NumIntRegs; ireg++) { 7522864Sktlim@umich.edu PhysRegIndex phys_reg = freeList.getIntReg(); 7532864Sktlim@umich.edu 7542864Sktlim@umich.edu renameMap[tid].setEntry(ireg,phys_reg); 7552864Sktlim@umich.edu scoreboard.setReg(phys_reg); 7562864Sktlim@umich.edu } 7572864Sktlim@umich.edu 7582864Sktlim@umich.edu //Bind Float Regs to Rename Map 7592864Sktlim@umich.edu for (int freg = 0; freg < TheISA::NumFloatRegs; freg++) { 7602864Sktlim@umich.edu PhysRegIndex phys_reg = freeList.getFloatReg(); 7612864Sktlim@umich.edu 7622864Sktlim@umich.edu renameMap[tid].setEntry(freg,phys_reg); 7632864Sktlim@umich.edu scoreboard.setReg(phys_reg); 7642864Sktlim@umich.edu } 7652864Sktlim@umich.edu 7662864Sktlim@umich.edu //Copy Thread Data Into RegFile 7672864Sktlim@umich.edu //this->copyFromTC(tid); 7682864Sktlim@umich.edu 7692864Sktlim@umich.edu //Set PC/NPC/NNPC 7702864Sktlim@umich.edu pcState(src_tc->pcState(), tid); 7712864Sktlim@umich.edu 7722864Sktlim@umich.edu src_tc->setStatus(ThreadContext::Active); 7732864Sktlim@umich.edu 7742864Sktlim@umich.edu activateContext(tid,1); 7752864Sktlim@umich.edu 7762864Sktlim@umich.edu //Reset ROB/IQ/LSQ Entries 7772864Sktlim@umich.edu commit.rob->resetEntries(); 7782864Sktlim@umich.edu iew.resetEntries(); 7792864Sktlim@umich.edu} 7802864Sktlim@umich.edu 7812864Sktlim@umich.edutemplate <class Impl> 7822864Sktlim@umich.eduvoid 7832864Sktlim@umich.eduFullO3CPU<Impl>::removeThread(ThreadID tid) 7842864Sktlim@umich.edu{ 7852864Sktlim@umich.edu DPRINTF(O3CPU,"[tid:%i] Removing thread context from CPU.\n", tid); 7862905Sktlim@umich.edu 7872843Sktlim@umich.edu // Copy Thread Data From RegFile 7881060SN/A // If thread is suspended, it might be re-allocated 7892843Sktlim@umich.edu // this->copyToTC(tid); 7902843Sktlim@umich.edu 7912843Sktlim@umich.edu 7922843Sktlim@umich.edu // @todo: 2-27-2008: Fix how we free up rename mappings 7932843Sktlim@umich.edu // here to alleviate the case for double-freeing registers 7942843Sktlim@umich.edu // in SMT workloads. 7952325SN/A 7962325SN/A // Unbind Int Regs from Rename Map 7972863Sktlim@umich.edu for (int ireg = 0; ireg < TheISA::NumIntRegs; ireg++) { 7982905Sktlim@umich.edu PhysRegIndex phys_reg = renameMap[tid].lookup(ireg); 7992864Sktlim@umich.edu 8002864Sktlim@umich.edu scoreboard.unsetReg(phys_reg); 8012864Sktlim@umich.edu freeList.addReg(phys_reg); 8022864Sktlim@umich.edu } 8032864Sktlim@umich.edu 8042843Sktlim@umich.edu // Unbind Float Regs from Rename Map 8052863Sktlim@umich.edu for (int freg = TheISA::NumIntRegs; freg < TheISA::NumFloatRegs; freg++) { 8062863Sktlim@umich.edu PhysRegIndex phys_reg = renameMap[tid].lookup(freg); 8072852Sktlim@umich.edu 8082905Sktlim@umich.edu scoreboard.unsetReg(phys_reg); 8092863Sktlim@umich.edu freeList.addReg(phys_reg); 8102905Sktlim@umich.edu } 8112863Sktlim@umich.edu 8122316SN/A // Squash Throughout Pipeline 8132310SN/A DynInstPtr inst = commit.rob->readHeadInst(tid); 8142316SN/A InstSeqNum squash_seq_num = inst->seqNum; 8152316SN/A fetch.squash(0, squash_seq_num, inst, tid); 8162843Sktlim@umich.edu decode.squash(tid); 8172316SN/A rename.squash(squash_seq_num, tid); 8182905Sktlim@umich.edu iew.squash(tid); 8192843Sktlim@umich.edu iew.ldstQueue.squash(squash_seq_num, tid); 8202843Sktlim@umich.edu commit.rob->squash(squash_seq_num, tid); 8212843Sktlim@umich.edu 8222843Sktlim@umich.edu 8232843Sktlim@umich.edu assert(iew.instQueue.getCount(tid) == 0); 8242316SN/A assert(iew.ldstQueue.getCount(tid) == 0); 8252905Sktlim@umich.edu 8262905Sktlim@umich.edu // Reset ROB/IQ/LSQ Entries 8272864Sktlim@umich.edu 8282864Sktlim@umich.edu // Commented out for now. This should be possible to do by 8292864Sktlim@umich.edu // telling all the pipeline stages to drain first, and then 8302843Sktlim@umich.edu // checking until the drain completes. Once the pipeline is 8312843Sktlim@umich.edu // drained, call resetEntries(). - 10-09-06 ktlim 8322843Sktlim@umich.edu/* 8332843Sktlim@umich.edu if (activeThreads.size() >= 1) { 8342316SN/A commit.rob->resetEntries(); 8352843Sktlim@umich.edu iew.resetEntries(); 8362843Sktlim@umich.edu } 8372843Sktlim@umich.edu*/ 8382843Sktlim@umich.edu} 8392843Sktlim@umich.edu 8402316SN/A 8412316SN/Atemplate <class Impl> 8422863Sktlim@umich.eduvoid 8432905Sktlim@umich.eduFullO3CPU<Impl>::activateWhenReady(ThreadID tid) 8442863Sktlim@umich.edu{ 8452863Sktlim@umich.edu DPRINTF(O3CPU,"[tid:%i]: Checking if resources are available for incoming" 8462863Sktlim@umich.edu "(e.g. PhysRegs/ROB/IQ/LSQ) \n", 8472863Sktlim@umich.edu tid); 8482863Sktlim@umich.edu 8492310SN/A bool ready = true; 8502843Sktlim@umich.edu 8512843Sktlim@umich.edu if (freeList.numFreeIntRegs() >= TheISA::NumIntRegs) { 8522843Sktlim@umich.edu DPRINTF(O3CPU,"[tid:%i] Suspending thread due to not enough " 8532843Sktlim@umich.edu "Phys. Int. Regs.\n", 8542843Sktlim@umich.edu tid); 8552843Sktlim@umich.edu ready = false; 8562843Sktlim@umich.edu } else if (freeList.numFreeFloatRegs() >= TheISA::NumFloatRegs) { 8572843Sktlim@umich.edu DPRINTF(O3CPU,"[tid:%i] Suspending thread due to not enough " 8582843Sktlim@umich.edu "Phys. Float. Regs.\n", 8592843Sktlim@umich.edu tid); 8602843Sktlim@umich.edu ready = false; 8612843Sktlim@umich.edu } else if (commit.rob->numFreeEntries() >= 8622843Sktlim@umich.edu commit.rob->entryAmount(activeThreads.size() + 1)) { 8632843Sktlim@umich.edu DPRINTF(O3CPU,"[tid:%i] Suspending thread due to not enough " 8642843Sktlim@umich.edu "ROB entries.\n", 8652843Sktlim@umich.edu tid); 8662843Sktlim@umich.edu ready = false; 8672843Sktlim@umich.edu } else if (iew.instQueue.numFreeEntries() >= 8682843Sktlim@umich.edu iew.instQueue.entryAmount(activeThreads.size() + 1)) { 8692843Sktlim@umich.edu DPRINTF(O3CPU,"[tid:%i] Suspending thread due to not enough " 8701060SN/A "IQ entries.\n", 8711060SN/A tid); 8721060SN/A ready = false; 8731060SN/A } else if (iew.ldstQueue.numFreeEntries() >= 8741755SN/A iew.ldstQueue.entryAmount(activeThreads.size() + 1)) { 8751060SN/A DPRINTF(O3CPU,"[tid:%i] Suspending thread due to not enough " 8762325SN/A "LSQ entries.\n", 8772873Sktlim@umich.edu tid); 8782307SN/A ready = false; 8792307SN/A } 8802307SN/A 8812307SN/A if (ready) { 8822307SN/A insertThread(tid); 8832307SN/A 8842307SN/A contextSwitch = false; 8852325SN/A 8862307SN/A cpuWaitList.remove(tid); 8871060SN/A } else { 8881060SN/A suspendContext(tid); 8892307SN/A 8902307SN/A //blocks fetch 8912307SN/A contextSwitch = true; 8922307SN/A 8932307SN/A //@todo: dont always add to waitlist 8942307SN/A //do waitlist 8951060SN/A cpuWaitList.push_back(tid); 8961060SN/A } 8972325SN/A} 8982325SN/A 8992307SN/A#if FULL_SYSTEM 9002307SN/Atemplate <class Impl> 9012307SN/AFault 9022307SN/AFullO3CPU<Impl>::hwrei(ThreadID tid) 9032307SN/A{ 9042307SN/A#if THE_ISA == ALPHA_ISA 9052325SN/A // Need to clear the lock flag upon returning from an interrupt. 9062325SN/A this->setMiscRegNoEffect(AlphaISA::MISCREG_LOCKFLAG, false, tid); 9072733Sktlim@umich.edu 9082307SN/A this->thread[tid]->kernelStats->hwrei(); 9092307SN/A 9102307SN/A // FIXME: XXX check for interrupts? XXX 9112307SN/A#endif 9122307SN/A return NoFault; 9132325SN/A} 9142307SN/A 9152680Sktlim@umich.edutemplate <class Impl> 9162680Sktlim@umich.edubool 9172680Sktlim@umich.eduFullO3CPU<Impl>::simPalCheck(int palFunc, ThreadID tid) 9181681SN/A{ 9191681SN/A#if THE_ISA == ALPHA_ISA 9201681SN/A if (this->thread[tid]->kernelStats) 9211060SN/A this->thread[tid]->kernelStats->callpal(palFunc, 9222307SN/A this->threadContexts[tid]); 9232307SN/A 9241060SN/A switch (palFunc) { 9251060SN/A case PAL::halt: 9261060SN/A halt(); 9271060SN/A if (--System::numSystemsRunning == 0) 9281755SN/A exitSimLoop("all cpus halted"); 9291060SN/A break; 9301060SN/A 9311060SN/A case PAL::bpt: 9321060SN/A case PAL::bugchk: 9331060SN/A if (this->system->breakpoint()) 9342455SN/A return false; 9352455SN/A break; 9361060SN/A } 9372455SN/A#endif 9381060SN/A return true; 9391060SN/A} 9401060SN/A 9412455SN/Atemplate <class Impl> 9422455SN/AFault 9431060SN/AFullO3CPU<Impl>::getInterrupts() 9442455SN/A{ 9451060SN/A // Check if there are any outstanding interrupts 9461060SN/A return this->interrupts->getInterrupt(this->threadContexts[0]); 9471060SN/A} 9482455SN/A 9492455SN/Atemplate <class Impl> 9501060SN/Avoid 9512455SN/AFullO3CPU<Impl>::processInterrupts(Fault interrupt) 9522455SN/A{ 9532455SN/A // Check for interrupts here. For now can copy the code that 9542455SN/A // exists within isa_fullsys_traits.hh. Also assume that thread 0 9552455SN/A // is the one that handles the interrupts. 9562455SN/A // @todo: Possibly consolidate the interrupt checking code. 9572455SN/A // @todo: Allow other threads to handle interrupts. 9582455SN/A 9591060SN/A assert(interrupt != NoFault); 9601060SN/A this->interrupts->updateIntrInfo(this->threadContexts[0]); 9611060SN/A 9621060SN/A DPRINTF(O3CPU, "Interrupt %s being handled\n", interrupt->name()); 9631755SN/A this->trap(interrupt, 0, NULL); 9641060SN/A} 9651060SN/A 9661060SN/Atemplate <class Impl> 9671060SN/Avoid 9681060SN/AFullO3CPU<Impl>::updateMemPorts() 9691060SN/A{ 9702455SN/A // Update all ThreadContext's memory ports (Functional/Virtual 9711060SN/A // Ports) 9722455SN/A ThreadID size = thread.size(); 9731060SN/A for (ThreadID i = 0; i < size; ++i) 9741060SN/A thread[i]->connectMemPorts(thread[i]->getTC()); 9751060SN/A} 9761060SN/A#endif 9772455SN/A 9781060SN/Atemplate <class Impl> 9792455SN/Avoid 9801060SN/AFullO3CPU<Impl>::trap(Fault fault, ThreadID tid, StaticInstPtr inst) 9811060SN/A{ 9821060SN/A // Pass the thread's TC into the invoke method. 9831060SN/A fault->invoke(this->threadContexts[tid], inst); 9842455SN/A} 9851060SN/A 9862455SN/A#if !FULL_SYSTEM 9872455SN/A 9882455SN/Atemplate <class Impl> 9892455SN/Avoid 9902455SN/AFullO3CPU<Impl>::syscall(int64_t callnum, ThreadID tid) 9912455SN/A{ 9922455SN/A DPRINTF(O3CPU, "[tid:%i] Executing syscall().\n\n", tid); 9932455SN/A 9941060SN/A DPRINTF(Activity,"Activity: syscall() called.\n"); 9951060SN/A 9961060SN/A // Temporarily increase this by one to account for the syscall 9971060SN/A // instruction. 9982292SN/A ++(this->thread[tid]->funcExeInst); 9991060SN/A 10002292SN/A // Execute the actual syscall. 10012292SN/A this->thread[tid]->syscall(callnum); 10022292SN/A 10032292SN/A // Decrease funcExeInst by one as the normal commit will handle 10042292SN/A // incrementing it. 10052292SN/A --(this->thread[tid]->funcExeInst); 10062292SN/A} 10072292SN/A 10082292SN/A#endif 10092307SN/A 10102307SN/Atemplate <class Impl> 10112292SN/Avoid 10122669Sktlim@umich.eduFullO3CPU<Impl>::serialize(std::ostream &os) 10132292SN/A{ 10142292SN/A SimObject::State so_state = SimObject::getState(); 10152292SN/A SERIALIZE_ENUM(so_state); 10162292SN/A BaseCPU::serialize(os); 10172292SN/A nameOut(os, csprintf("%s.tickEvent", name())); 10182292SN/A tickEvent.serialize(os); 10192307SN/A 10202307SN/A // Use SimpleThread's ability to checkpoint to make it easier to 10212292SN/A // write out the registers. Also make this static so it doesn't 10222669Sktlim@umich.edu // get instantiated multiple times (causes a panic in statistics). 10232292SN/A static SimpleThread temp; 10242292SN/A 10252292SN/A ThreadID size = thread.size(); 10262292SN/A for (ThreadID i = 0; i < size; i++) { 10272292SN/A nameOut(os, csprintf("%s.xc.%i", name(), i)); 10282292SN/A temp.copyTC(thread[i]->getTC()); 10292307SN/A temp.serialize(os); 10302307SN/A } 10312292SN/A} 10322669Sktlim@umich.edu 10331060SN/Atemplate <class Impl> 10341060SN/Avoid 10351060SN/AFullO3CPU<Impl>::unserialize(Checkpoint *cp, const std::string §ion) 10361060SN/A{ 10372292SN/A SimObject::State so_state; 10381060SN/A UNSERIALIZE_ENUM(so_state); 10392292SN/A BaseCPU::unserialize(cp, section); 10402292SN/A tickEvent.unserialize(cp, csprintf("%s.tickEvent", section)); 10412292SN/A 10421060SN/A // Use SimpleThread's ability to checkpoint to make it easier to 10431060SN/A // read in the registers. Also make this static so it doesn't 10441060SN/A // get instantiated multiple times (causes a panic in statistics). 10451060SN/A static SimpleThread temp; 10462292SN/A 10471060SN/A ThreadID size = thread.size(); 10482292SN/A for (ThreadID i = 0; i < size; i++) { 10492292SN/A temp.copyTC(thread[i]->getTC()); 10502669Sktlim@umich.edu temp.unserialize(cp, csprintf("%s.xc.%i", section, i)); 10511060SN/A thread[i]->getTC()->copyArchRegs(temp.getTC()); 10521060SN/A } 10531060SN/A} 10541060SN/A 10552292SN/Atemplate <class Impl> 10561060SN/Aunsigned int 10572292SN/AFullO3CPU<Impl>::drain(Event *drain_event) 10582292SN/A{ 10592669Sktlim@umich.edu DPRINTF(O3CPU, "Switching out\n"); 10601060SN/A 10611060SN/A // If the CPU isn't doing anything, then return immediately. 10621060SN/A if (_status == Idle || _status == SwitchedOut) { 10631060SN/A return 0; 10642292SN/A } 10651060SN/A 10662292SN/A drainCount = 0; 10671060SN/A fetch.drain(); 10682669Sktlim@umich.edu decode.drain(); 10692292SN/A rename.drain(); 10702292SN/A iew.drain(); 10712292SN/A commit.drain(); 10722292SN/A 10732292SN/A // Wake the CPU and record activity so everything can drain out if 10742292SN/A // the CPU was not able to immediately drain. 10752292SN/A if (getState() != SimObject::Drained) { 10761060SN/A // A bit of a hack...set the drainEvent after all the drain() 10771060SN/A // calls have been made, that way if all of the stages drain 10781060SN/A // immediately, the signalDrained() function knows not to call 10791060SN/A // process on the drain event. 10802292SN/A drainEvent = drain_event; 10811060SN/A 10822292SN/A wakeCPU(); 10832292SN/A activityRec.activity(); 10841060SN/A 10852292SN/A return 1; 10862292SN/A } else { 10872292SN/A return 0; 10882292SN/A } 10892292SN/A} 10902292SN/A 10911060SN/Atemplate <class Impl> 10922292SN/Avoid 10932292SN/AFullO3CPU<Impl>::resume() 10942292SN/A{ 10952292SN/A fetch.resume(); 10962292SN/A decode.resume(); 10972292SN/A rename.resume(); 10981060SN/A iew.resume(); 10992756Sksewell@umich.edu commit.resume(); 11002756Sksewell@umich.edu 11012756Sksewell@umich.edu changeState(SimObject::Running); 11022756Sksewell@umich.edu 11032756Sksewell@umich.edu if (_status == SwitchedOut || _status == Idle) 11042756Sksewell@umich.edu return; 11052756Sksewell@umich.edu 11062756Sksewell@umich.edu assert(system->getMemoryMode() == Enums::timing); 11072756Sksewell@umich.edu 11082756Sksewell@umich.edu if (!tickEvent.scheduled()) 11092756Sksewell@umich.edu schedule(tickEvent, nextCycle()); 11102756Sksewell@umich.edu _status = Running; 11112756Sksewell@umich.edu} 11122756Sksewell@umich.edu 11132756Sksewell@umich.edutemplate <class Impl> 11142756Sksewell@umich.eduvoid 11152292SN/AFullO3CPU<Impl>::signalDrained() 11162292SN/A{ 11172292SN/A if (++drainCount == NumStages) { 11182292SN/A if (tickEvent.scheduled()) 11192292SN/A tickEvent.squash(); 11201060SN/A 11212292SN/A changeState(SimObject::Drained); 11222292SN/A 11231060SN/A BaseCPU::switchOut(); 11242292SN/A 11252292SN/A if (drainEvent) { 11262292SN/A drainEvent->process(); 11272292SN/A drainEvent = NULL; 11282292SN/A } 11292292SN/A } 11302292SN/A assert(drainCount <= 5); 11312292SN/A} 11322292SN/A 11332292SN/Atemplate <class Impl> 11342292SN/Avoid 11352292SN/AFullO3CPU<Impl>::switchOut() 11362292SN/A{ 11372292SN/A fetch.switchOut(); 11382292SN/A rename.switchOut(); 11392292SN/A iew.switchOut(); 11402292SN/A commit.switchOut(); 11412292SN/A instList.clear(); 11422292SN/A while (!removeList.empty()) { 11432292SN/A removeList.pop(); 11442292SN/A } 11451060SN/A 11461060SN/A _status = SwitchedOut; 11471060SN/A#if USE_CHECKER 11481060SN/A if (checker) 11491755SN/A checker->switchOut(); 11501060SN/A#endif 11512733Sktlim@umich.edu if (tickEvent.scheduled()) 11522292SN/A tickEvent.squash(); 11532303SN/A} 11541060SN/A 11552292SN/Atemplate <class Impl> 11561060SN/Avoid 11571060SN/AFullO3CPU<Impl>::takeOverFrom(BaseCPU *oldCPU) 11582292SN/A{ 11591060SN/A // Flush out any old data from the time buffers. 11601060SN/A for (int i = 0; i < timeBuffer.getSize(); ++i) { 11611060SN/A timeBuffer.advance(); 11621060SN/A fetchQueue.advance(); 11632292SN/A decodeQueue.advance(); 11641060SN/A renameQueue.advance(); 11652733Sktlim@umich.edu iewQueue.advance(); 11662292SN/A } 11671060SN/A 11682292SN/A activityRec.reset(); 11691060SN/A 11702292SN/A BaseCPU::takeOverFrom(oldCPU, fetch.getIcachePort(), iew.getDcachePort()); 11712292SN/A 11722292SN/A fetch.takeOverFrom(); 11732292SN/A decode.takeOverFrom(); 11742292SN/A rename.takeOverFrom(); 11752733Sktlim@umich.edu iew.takeOverFrom(); 11762292SN/A commit.takeOverFrom(); 11772292SN/A 11782292SN/A assert(!tickEvent.scheduled() || tickEvent.squashed()); 11792292SN/A 11802733Sktlim@umich.edu // @todo: Figure out how to properly select the tid to put onto 11812292SN/A // the active threads list. 11822292SN/A ThreadID tid = 0; 11832292SN/A 11842292SN/A list<ThreadID>::iterator isActive = 11852292SN/A std::find(activeThreads.begin(), activeThreads.end(), tid); 11862292SN/A 11872292SN/A if (isActive == activeThreads.end()) { 11882292SN/A //May Need to Re-code this if the delay variable is the delay 11892292SN/A //needed for thread to activate 11902292SN/A DPRINTF(O3CPU, "Adding Thread %i to active threads list\n", 11912292SN/A tid); 11922292SN/A 11932292SN/A activeThreads.push_back(tid); 11942292SN/A } 11952292SN/A 11962292SN/A // Set all statuses to active, schedule the CPU's tick event. 11972292SN/A // @todo: Fix up statuses so this is handled properly 11982292SN/A ThreadID size = threadContexts.size(); 11992292SN/A for (ThreadID i = 0; i < size; ++i) { 12002292SN/A ThreadContext *tc = threadContexts[i]; 12012292SN/A if (tc->status() == ThreadContext::Active && _status != Running) { 12022292SN/A _status = Running; 12032292SN/A reschedule(tickEvent, nextCycle(), true); 12041060SN/A } 12051060SN/A } 12061060SN/A if (!tickEvent.scheduled()) 12071060SN/A schedule(tickEvent, nextCycle()); 12082292SN/A} 12092292SN/A 12101062SN/Atemplate <class Impl> 12112292SN/ATheISA::MiscReg 12122292SN/AFullO3CPU<Impl>::readMiscRegNoEffect(int misc_reg, ThreadID tid) 12132292SN/A{ 12142292SN/A return this->isa[tid].readMiscRegNoEffect(misc_reg); 12152292SN/A} 12162292SN/A 12172292SN/Atemplate <class Impl> 12182292SN/ATheISA::MiscReg 12192733Sktlim@umich.eduFullO3CPU<Impl>::readMiscReg(int misc_reg, ThreadID tid) 12202292SN/A{ 12212292SN/A miscRegfileReads++; 12221062SN/A return this->isa[tid].readMiscReg(misc_reg, tcBase(tid)); 12232292SN/A} 12241062SN/A 12252292SN/Atemplate <class Impl> 12261062SN/Avoid 12272292SN/AFullO3CPU<Impl>::setMiscRegNoEffect(int misc_reg, 12281062SN/A const TheISA::MiscReg &val, ThreadID tid) 12292292SN/A{ 12301062SN/A this->isa[tid].setMiscRegNoEffect(misc_reg, val); 12312292SN/A} 12322292SN/A 12332292SN/Atemplate <class Impl> 12342292SN/Avoid 12352292SN/AFullO3CPU<Impl>::setMiscReg(int misc_reg, 12362292SN/A const TheISA::MiscReg &val, ThreadID tid) 12372292SN/A{ 12382292SN/A miscRegfileWrites++; 12392292SN/A this->isa[tid].setMiscReg(misc_reg, val, tcBase(tid)); 12402292SN/A} 12412733Sktlim@umich.edu 12422292SN/Atemplate <class Impl> 12432292SN/Auint64_t 12442292SN/AFullO3CPU<Impl>::readIntReg(int reg_idx) 12452292SN/A{ 12461062SN/A intRegfileReads++; 12471062SN/A return regFile.readIntReg(reg_idx); 12482292SN/A} 12492292SN/A 12502325SN/Atemplate <class Impl> 12512325SN/AFloatReg 12522292SN/AFullO3CPU<Impl>::readFloatReg(int reg_idx) 12532292SN/A{ 12542292SN/A fpRegfileReads++; 12552292SN/A return regFile.readFloatReg(reg_idx); 12562292SN/A} 12572292SN/A 12582292SN/Atemplate <class Impl> 12592292SN/AFloatRegBits 12602292SN/AFullO3CPU<Impl>::readFloatRegBits(int reg_idx) 12612292SN/A{ 12622733Sktlim@umich.edu fpRegfileReads++; 12632292SN/A return regFile.readFloatRegBits(reg_idx); 12642292SN/A} 12652292SN/A 12662292SN/Atemplate <class Impl> 12672292SN/Avoid 12682292SN/AFullO3CPU<Impl>::setIntReg(int reg_idx, uint64_t val) 12692292SN/A{ 12702292SN/A intRegfileWrites++; 12711062SN/A regFile.setIntReg(reg_idx, val); 12721062SN/A} 12732292SN/A 12741062SN/Atemplate <class Impl> 12752325SN/Avoid 12761062SN/AFullO3CPU<Impl>::setFloatReg(int reg_idx, FloatReg val) 12771062SN/A{ 12781755SN/A fpRegfileWrites++; 12791060SN/A regFile.setFloatReg(reg_idx, val); 12801060SN/A} 12811060SN/A 12822325SN/Atemplate <class Impl> 12831060SN/Avoid 12841060SN/AFullO3CPU<Impl>::setFloatRegBits(int reg_idx, FloatRegBits val) 12851755SN/A{ 12861060SN/A fpRegfileWrites++; 12871060SN/A regFile.setFloatRegBits(reg_idx, val); 12881060SN/A} 12892292SN/A 12902292SN/Atemplate <class Impl> 12912292SN/Auint64_t 12922292SN/AFullO3CPU<Impl>::readArchIntReg(int reg_idx, ThreadID tid) 12932292SN/A{ 12942292SN/A intRegfileReads++; 12952292SN/A PhysRegIndex phys_reg = commitRenameMap[tid].lookup(reg_idx); 12962292SN/A 12972292SN/A return regFile.readIntReg(phys_reg); 12982292SN/A} 12991060SN/A 13001060SN/Atemplate <class Impl> 13011060SN/Afloat 13021060SN/AFullO3CPU<Impl>::readArchFloatReg(int reg_idx, ThreadID tid) 13032325SN/A{ 13041060SN/A fpRegfileReads++; 13051060SN/A int idx = reg_idx + TheISA::NumIntRegs; 13061755SN/A PhysRegIndex phys_reg = commitRenameMap[tid].lookup(idx); 13071060SN/A 13081060SN/A return regFile.readFloatReg(phys_reg); 13091060SN/A} 13102325SN/A 13112292SN/Atemplate <class Impl> 13122292SN/Auint64_t 13132292SN/AFullO3CPU<Impl>::readArchFloatRegInt(int reg_idx, ThreadID tid) 13142292SN/A{ 13152325SN/A fpRegfileReads++; 13162325SN/A int idx = reg_idx + TheISA::NumIntRegs; 13172292SN/A PhysRegIndex phys_reg = commitRenameMap[tid].lookup(idx); 13182292SN/A 13192292SN/A return regFile.readFloatRegBits(phys_reg); 13202325SN/A} 13212325SN/A 13222325SN/Atemplate <class Impl> 13232292SN/Avoid 13242292SN/AFullO3CPU<Impl>::setArchIntReg(int reg_idx, uint64_t val, ThreadID tid) 13252292SN/A{ 13262292SN/A intRegfileWrites++; 13272292SN/A PhysRegIndex phys_reg = commitRenameMap[tid].lookup(reg_idx); 13282292SN/A 13292292SN/A regFile.setIntReg(phys_reg, val); 13302292SN/A} 13312292SN/A 13322292SN/Atemplate <class Impl> 13332292SN/Avoid 13342292SN/AFullO3CPU<Impl>::setArchFloatReg(int reg_idx, float val, ThreadID tid) 13352292SN/A{ 13362292SN/A fpRegfileWrites++; 13372292SN/A int idx = reg_idx + TheISA::NumIntRegs; 13382292SN/A PhysRegIndex phys_reg = commitRenameMap[tid].lookup(idx); 13392292SN/A 13402292SN/A regFile.setFloatReg(phys_reg, val); 13412292SN/A} 13422292SN/A 13432292SN/Atemplate <class Impl> 13442292SN/Avoid 13452292SN/AFullO3CPU<Impl>::setArchFloatRegInt(int reg_idx, uint64_t val, ThreadID tid) 13462292SN/A{ 13472292SN/A fpRegfileWrites++; 13482292SN/A int idx = reg_idx + TheISA::NumIntRegs; 13492292SN/A PhysRegIndex phys_reg = commitRenameMap[tid].lookup(idx); 13502292SN/A 13512292SN/A regFile.setFloatRegBits(phys_reg, val); 13522292SN/A} 13532292SN/A 13542292SN/Atemplate <class Impl> 13552292SN/ATheISA::PCState 13562292SN/AFullO3CPU<Impl>::pcState(ThreadID tid) 13572292SN/A{ 13582292SN/A return commit.pcState(tid); 13592292SN/A} 13602292SN/A 13612292SN/Atemplate <class Impl> 13622292SN/Avoid 13632292SN/AFullO3CPU<Impl>::pcState(const TheISA::PCState &val, ThreadID tid) 13642292SN/A{ 13652292SN/A commit.pcState(val, tid); 13662292SN/A} 13672292SN/A 13682292SN/Atemplate <class Impl> 13692292SN/AAddr 13702292SN/AFullO3CPU<Impl>::instAddr(ThreadID tid) 13712292SN/A{ 13722292SN/A return commit.instAddr(tid); 13732292SN/A} 13742292SN/A 13752292SN/Atemplate <class Impl> 13761060SN/AAddr 13771755SN/AFullO3CPU<Impl>::nextInstAddr(ThreadID tid) 13782818Sksewell@umich.edu{ 1379 return commit.nextInstAddr(tid); 1380} 1381 1382template <class Impl> 1383MicroPC 1384FullO3CPU<Impl>::microPC(ThreadID tid) 1385{ 1386 return commit.microPC(tid); 1387} 1388 1389template <class Impl> 1390void 1391FullO3CPU<Impl>::squashFromTC(ThreadID tid) 1392{ 1393 this->thread[tid]->inSyscall = true; 1394 this->commit.generateTCEvent(tid); 1395} 1396 1397template <class Impl> 1398typename FullO3CPU<Impl>::ListIt 1399FullO3CPU<Impl>::addInst(DynInstPtr &inst) 1400{ 1401 instList.push_back(inst); 1402 1403 return --(instList.end()); 1404} 1405 1406template <class Impl> 1407void 1408FullO3CPU<Impl>::instDone(ThreadID tid) 1409{ 1410 // Keep an instruction count. 1411 thread[tid]->numInst++; 1412 thread[tid]->numInsts++; 1413 committedInsts[tid]++; 1414 totalCommittedInsts++; 1415 system->totalNumInsts++; 1416 // Check for instruction-count-based events. 1417 comInstEventQueue[tid]->serviceEvents(thread[tid]->numInst); 1418 system->instEventQueue.serviceEvents(system->totalNumInsts); 1419} 1420 1421template <class Impl> 1422void 1423FullO3CPU<Impl>::removeFrontInst(DynInstPtr &inst) 1424{ 1425 DPRINTF(O3CPU, "Removing committed instruction [tid:%i] PC %s " 1426 "[sn:%lli]\n", 1427 inst->threadNumber, inst->pcState(), inst->seqNum); 1428 1429 removeInstsThisCycle = true; 1430 1431 // Remove the front instruction. 1432 removeList.push(inst->getInstListIt()); 1433} 1434 1435template <class Impl> 1436void 1437FullO3CPU<Impl>::removeInstsNotInROB(ThreadID tid) 1438{ 1439 DPRINTF(O3CPU, "Thread %i: Deleting instructions from instruction" 1440 " list.\n", tid); 1441 1442 ListIt end_it; 1443 1444 bool rob_empty = false; 1445 1446 if (instList.empty()) { 1447 return; 1448 } else if (rob.isEmpty(/*tid*/)) { 1449 DPRINTF(O3CPU, "ROB is empty, squashing all insts.\n"); 1450 end_it = instList.begin(); 1451 rob_empty = true; 1452 } else { 1453 end_it = (rob.readTailInst(tid))->getInstListIt(); 1454 DPRINTF(O3CPU, "ROB is not empty, squashing insts not in ROB.\n"); 1455 } 1456 1457 removeInstsThisCycle = true; 1458 1459 ListIt inst_it = instList.end(); 1460 1461 inst_it--; 1462 1463 // Walk through the instruction list, removing any instructions 1464 // that were inserted after the given instruction iterator, end_it. 1465 while (inst_it != end_it) { 1466 assert(!instList.empty()); 1467 1468 squashInstIt(inst_it, tid); 1469 1470 inst_it--; 1471 } 1472 1473 // If the ROB was empty, then we actually need to remove the first 1474 // instruction as well. 1475 if (rob_empty) { 1476 squashInstIt(inst_it, tid); 1477 } 1478} 1479 1480template <class Impl> 1481void 1482FullO3CPU<Impl>::removeInstsUntil(const InstSeqNum &seq_num, ThreadID tid) 1483{ 1484 assert(!instList.empty()); 1485 1486 removeInstsThisCycle = true; 1487 1488 ListIt inst_iter = instList.end(); 1489 1490 inst_iter--; 1491 1492 DPRINTF(O3CPU, "Deleting instructions from instruction " 1493 "list that are from [tid:%i] and above [sn:%lli] (end=%lli).\n", 1494 tid, seq_num, (*inst_iter)->seqNum); 1495 1496 while ((*inst_iter)->seqNum > seq_num) { 1497 1498 bool break_loop = (inst_iter == instList.begin()); 1499 1500 squashInstIt(inst_iter, tid); 1501 1502 inst_iter--; 1503 1504 if (break_loop) 1505 break; 1506 } 1507} 1508 1509template <class Impl> 1510inline void 1511FullO3CPU<Impl>::squashInstIt(const ListIt &instIt, ThreadID tid) 1512{ 1513 if ((*instIt)->threadNumber == tid) { 1514 DPRINTF(O3CPU, "Squashing instruction, " 1515 "[tid:%i] [sn:%lli] PC %s\n", 1516 (*instIt)->threadNumber, 1517 (*instIt)->seqNum, 1518 (*instIt)->pcState()); 1519 1520 // Mark it as squashed. 1521 (*instIt)->setSquashed(); 1522 1523 // @todo: Formulate a consistent method for deleting 1524 // instructions from the instruction list 1525 // Remove the instruction from the list. 1526 removeList.push(instIt); 1527 } 1528} 1529 1530template <class Impl> 1531void 1532FullO3CPU<Impl>::cleanUpRemovedInsts() 1533{ 1534 while (!removeList.empty()) { 1535 DPRINTF(O3CPU, "Removing instruction, " 1536 "[tid:%i] [sn:%lli] PC %s\n", 1537 (*removeList.front())->threadNumber, 1538 (*removeList.front())->seqNum, 1539 (*removeList.front())->pcState()); 1540 1541 instList.erase(removeList.front()); 1542 1543 removeList.pop(); 1544 } 1545 1546 removeInstsThisCycle = false; 1547} 1548/* 1549template <class Impl> 1550void 1551FullO3CPU<Impl>::removeAllInsts() 1552{ 1553 instList.clear(); 1554} 1555*/ 1556template <class Impl> 1557void 1558FullO3CPU<Impl>::dumpInsts() 1559{ 1560 int num = 0; 1561 1562 ListIt inst_list_it = instList.begin(); 1563 1564 cprintf("Dumping Instruction List\n"); 1565 1566 while (inst_list_it != instList.end()) { 1567 cprintf("Instruction:%i\nPC:%#x\n[tid:%i]\n[sn:%lli]\nIssued:%i\n" 1568 "Squashed:%i\n\n", 1569 num, (*inst_list_it)->instAddr(), (*inst_list_it)->threadNumber, 1570 (*inst_list_it)->seqNum, (*inst_list_it)->isIssued(), 1571 (*inst_list_it)->isSquashed()); 1572 inst_list_it++; 1573 ++num; 1574 } 1575} 1576/* 1577template <class Impl> 1578void 1579FullO3CPU<Impl>::wakeDependents(DynInstPtr &inst) 1580{ 1581 iew.wakeDependents(inst); 1582} 1583*/ 1584template <class Impl> 1585void 1586FullO3CPU<Impl>::wakeCPU() 1587{ 1588 if (activityRec.active() || tickEvent.scheduled()) { 1589 DPRINTF(Activity, "CPU already running.\n"); 1590 return; 1591 } 1592 1593 DPRINTF(Activity, "Waking up CPU\n"); 1594 1595 idleCycles += tickToCycles((curTick() - 1) - lastRunningCycle); 1596 numCycles += tickToCycles((curTick() - 1) - lastRunningCycle); 1597 1598 schedule(tickEvent, nextCycle()); 1599} 1600 1601#if FULL_SYSTEM 1602template <class Impl> 1603void 1604FullO3CPU<Impl>::wakeup() 1605{ 1606 if (this->thread[0]->status() != ThreadContext::Suspended) 1607 return; 1608 1609 this->wakeCPU(); 1610 1611 DPRINTF(Quiesce, "Suspended Processor woken\n"); 1612 this->threadContexts[0]->activate(); 1613} 1614#endif 1615 1616template <class Impl> 1617ThreadID 1618FullO3CPU<Impl>::getFreeTid() 1619{ 1620 for (ThreadID tid = 0; tid < numThreads; tid++) { 1621 if (!tids[tid]) { 1622 tids[tid] = true; 1623 return tid; 1624 } 1625 } 1626 1627 return InvalidThreadID; 1628} 1629 1630template <class Impl> 1631void 1632FullO3CPU<Impl>::doContextSwitch() 1633{ 1634 if (contextSwitch) { 1635 1636 //ADD CODE TO DEACTIVE THREAD HERE (???) 1637 1638 ThreadID size = cpuWaitList.size(); 1639 for (ThreadID tid = 0; tid < size; tid++) { 1640 activateWhenReady(tid); 1641 } 1642 1643 if (cpuWaitList.size() == 0) 1644 contextSwitch = true; 1645 } 1646} 1647 1648template <class Impl> 1649void 1650FullO3CPU<Impl>::updateThreadPriority() 1651{ 1652 if (activeThreads.size() > 1) { 1653 //DEFAULT TO ROUND ROBIN SCHEME 1654 //e.g. Move highest priority to end of thread list 1655 list<ThreadID>::iterator list_begin = activeThreads.begin(); 1656 list<ThreadID>::iterator list_end = activeThreads.end(); 1657 1658 unsigned high_thread = *list_begin; 1659 1660 activeThreads.erase(list_begin); 1661 1662 activeThreads.push_back(high_thread); 1663 } 1664} 1665 1666// Forward declaration of FullO3CPU. 1667template class FullO3CPU<O3CPUImpl>; 1668