cpu.cc revision 4329
12SN/A/* 21762SN/A * Copyright (c) 2004-2006 The Regents of The University of Michigan 32SN/A * All rights reserved. 42SN/A * 52SN/A * Redistribution and use in source and binary forms, with or without 62SN/A * modification, are permitted provided that the following conditions are 72SN/A * met: redistributions of source code must retain the above copyright 82SN/A * notice, this list of conditions and the following disclaimer; 92SN/A * redistributions in binary form must reproduce the above copyright 102SN/A * notice, this list of conditions and the following disclaimer in the 112SN/A * documentation and/or other materials provided with the distribution; 122SN/A * neither the name of the copyright holders nor the names of its 132SN/A * contributors may be used to endorse or promote products derived from 142SN/A * this software without specific prior written permission. 152SN/A * 162SN/A * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 172SN/A * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 182SN/A * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 192SN/A * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 202SN/A * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 212SN/A * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 222SN/A * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 232SN/A * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 242SN/A * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 252SN/A * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 262SN/A * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 272665Ssaidi@eecs.umich.edu * 282665Ssaidi@eecs.umich.edu * Authors: Kevin Lim 292665Ssaidi@eecs.umich.edu * Korey Sewell 302SN/A */ 312SN/A 321388SN/A#include "config/full_system.hh" 332SN/A#include "config/use_checker.hh" 342SN/A 352SN/A#if FULL_SYSTEM 361191SN/A#include "cpu/quiesce_event.hh" 371191SN/A#include "sim/system.hh" 381191SN/A#else 391388SN/A#include "sim/process.hh" 405529Snate@binkert.org#endif 411717SN/A 422651Ssaidi@eecs.umich.edu#include "cpu/activity.hh" 432680Sktlim@umich.edu#include "cpu/simple_thread.hh" 441977SN/A#include "cpu/thread_context.hh" 455529Snate@binkert.org#include "cpu/o3/isa_specific.hh" 463144Shsul@eecs.umich.edu#include "cpu/o3/cpu.hh" 472190SN/A 4856SN/A#include "sim/core.hh" 492190SN/A#include "sim/stat_control.hh" 502SN/A 512359SN/A#if USE_CHECKER 522359SN/A#include "cpu/checker/cpu.hh" 532359SN/A#endif 542SN/A 552SN/Ausing namespace std; 562SN/Ausing namespace TheISA; 572SN/A 582SN/ABaseO3CPU::BaseO3CPU(Params *params) 592SN/A : BaseCPU(params), cpu_id(0) 602SN/A{ 612SN/A} 622SN/A 635606Snate@binkert.orgvoid 645606Snate@binkert.orgBaseO3CPU::regStats() 655606Snate@binkert.org{ 663126Sktlim@umich.edu BaseCPU::regStats(); 673126Sktlim@umich.edu} 685606Snate@binkert.org 693126Sktlim@umich.edutemplate <class Impl> 703126Sktlim@umich.eduFullO3CPU<Impl>::TickEvent::TickEvent(FullO3CPU<Impl> *c) 712356SN/A : Event(&mainEventQueue, CPU_Tick_Pri), cpu(c) 722356SN/A{ 732356SN/A} 742367SN/A 752356SN/Atemplate <class Impl> 765100Ssaidi@eecs.umich.eduvoid 772367SN/AFullO3CPU<Impl>::TickEvent::process() 782356SN/A{ 792356SN/A cpu->tick(); 802356SN/A} 812367SN/A 822367SN/Atemplate <class Impl> 832367SN/Aconst char * 842367SN/AFullO3CPU<Impl>::TickEvent::description() 852356SN/A{ 865606Snate@binkert.org return "FullO3CPU tick event"; 872356SN/A} 882356SN/A 892356SN/Atemplate <class Impl> 905336Shines@cs.fsu.eduFullO3CPU<Impl>::ActivateThreadEvent::ActivateThreadEvent() 912356SN/A : Event(&mainEventQueue, CPU_Switch_Pri) 924873Sstever@eecs.umich.edu{ 932356SN/A} 942356SN/A 951858SN/Atemplate <class Impl> 961400SN/Avoid 975712Shsul@eecs.umich.eduFullO3CPU<Impl>::ActivateThreadEvent::init(int thread_num, 985712Shsul@eecs.umich.edu FullO3CPU<Impl> *thread_cpu) 995529Snate@binkert.org{ 1003661Srdreslin@umich.edu tid = thread_num; 1012SN/A cpu = thread_cpu; 1021400SN/A} 1035712Shsul@eecs.umich.edu 1045529Snate@binkert.orgtemplate <class Impl> 1053661Srdreslin@umich.eduvoid 1062SN/AFullO3CPU<Impl>::ActivateThreadEvent::process() 1072SN/A{ 1082359SN/A cpu->activateThread(tid); 1091062SN/A} 1105712Shsul@eecs.umich.edu 1115712Shsul@eecs.umich.edutemplate <class Impl> 1125712Shsul@eecs.umich.educonst char * 1135712Shsul@eecs.umich.eduFullO3CPU<Impl>::ActivateThreadEvent::description() 1145712Shsul@eecs.umich.edu{ 1152SN/A return "FullO3CPU \"Activate Thread\" event"; 1162SN/A} 1172SN/A 1185712Shsul@eecs.umich.edutemplate <class Impl> 1195712Shsul@eecs.umich.eduFullO3CPU<Impl>::DeallocateContextEvent::DeallocateContextEvent() 1202SN/A : Event(&mainEventQueue, CPU_Tick_Pri), tid(0), remove(false), cpu(NULL) 1212SN/A{ 1222SN/A} 1232SN/A 1241354SN/Atemplate <class Impl> 1252SN/Avoid 126503SN/AFullO3CPU<Impl>::DeallocateContextEvent::init(int thread_num, 1272SN/A FullO3CPU<Impl> *thread_cpu) 1282SN/A{ 1292SN/A tid = thread_num; 1302SN/A cpu = thread_cpu; 1315606Snate@binkert.org remove = false; 1325606Snate@binkert.org} 1335606Snate@binkert.org 1345606Snate@binkert.orgtemplate <class Impl> 1355606Snate@binkert.orgvoid 1365606Snate@binkert.orgFullO3CPU<Impl>::DeallocateContextEvent::process() 1375606Snate@binkert.org{ 1382SN/A cpu->deactivateThread(tid); 1391400SN/A if (remove) 1405606Snate@binkert.org cpu->removeThread(tid); 1415606Snate@binkert.org} 1422SN/A 1432SN/Atemplate <class Impl> 1442SN/Aconst char * 1452SN/AFullO3CPU<Impl>::DeallocateContextEvent::description() 1462SN/A{ 1475606Snate@binkert.org return "FullO3CPU \"Deallocate Context\" event"; 1485606Snate@binkert.org} 1495606Snate@binkert.org 1505606Snate@binkert.orgtemplate <class Impl> 1512SN/AFullO3CPU<Impl>::FullO3CPU(O3CPU *o3_cpu, Params *params) 1522SN/A : BaseO3CPU(params), 153124SN/A#if FULL_SYSTEM 1541354SN/A itb(params->itb), 155124SN/A dtb(params->dtb), 156124SN/A#endif 157124SN/A tickEvent(this), 158124SN/A removeInstsThisCycle(false), 159124SN/A fetch(o3_cpu, params), 160124SN/A decode(o3_cpu, params), 1615606Snate@binkert.org rename(o3_cpu, params), 1625606Snate@binkert.org iew(o3_cpu, params), 1635606Snate@binkert.org commit(o3_cpu, params), 1645606Snate@binkert.org 1655606Snate@binkert.org regFile(o3_cpu, params->numPhysIntRegs, 1665606Snate@binkert.org params->numPhysFloatRegs), 1675606Snate@binkert.org 168124SN/A freeList(params->numberOfThreads, 1691400SN/A TheISA::NumIntRegs, params->numPhysIntRegs, 1705606Snate@binkert.org TheISA::NumFloatRegs, params->numPhysFloatRegs), 171124SN/A 172124SN/A rob(o3_cpu, 173124SN/A params->numROBEntries, params->squashWidth, 174124SN/A params->smtROBPolicy, params->smtROBThreshold, 175124SN/A params->numberOfThreads), 1765606Snate@binkert.org 1775606Snate@binkert.org scoreboard(params->numberOfThreads, 1785606Snate@binkert.org TheISA::NumIntRegs, params->numPhysIntRegs, 1795606Snate@binkert.org TheISA::NumFloatRegs, params->numPhysFloatRegs, 180124SN/A TheISA::NumMiscRegs * number_of_threads, 181124SN/A TheISA::ZeroReg), 1821191SN/A 1835529Snate@binkert.org timeBuffer(params->backComSize, params->forwardComSize), 1841388SN/A fetchQueue(params->backComSize, params->forwardComSize), 1851191SN/A decodeQueue(params->backComSize, params->forwardComSize), 1865529Snate@binkert.org renameQueue(params->backComSize, params->forwardComSize), 1871191SN/A iewQueue(params->backComSize, params->forwardComSize), 1885529Snate@binkert.org activityRec(NumStages, 1891191SN/A params->backComSize + params->forwardComSize, 1901191SN/A params->activity), 1915606Snate@binkert.org 1925606Snate@binkert.org globalSeqNum(1), 1935606Snate@binkert.org#if FULL_SYSTEM 1941191SN/A system(params->system), 1951191SN/A physmem(system->physmem), 1961917SN/A#endif // FULL_SYSTEM 1971917SN/A drainCount(0), 1985529Snate@binkert.org deferRegistration(params->deferRegistration), 1995529Snate@binkert.org numThreads(number_of_threads) 2001917SN/A{ 2015529Snate@binkert.org if (!deferRegistration) { 2021917SN/A _status = Running; 2031191SN/A } else { 2041191SN/A _status = Idle; 2051191SN/A } 2061191SN/A 2071191SN/A checker = NULL; 2081191SN/A 2091191SN/A if (params->checker) { 2101191SN/A#if USE_CHECKER 2111191SN/A BaseCPU *temp_checker = params->checker; 2121191SN/A checker = dynamic_cast<Checker<DynInstPtr> *>(temp_checker); 2131191SN/A#if FULL_SYSTEM 2141129SN/A checker->setSystem(params->system); 2151129SN/A#endif 2161129SN/A#else 2175529Snate@binkert.org panic("Checker enabled but not compiled in!"); 2182680Sktlim@umich.edu#endif // USE_CHECKER 2191129SN/A } 220180SN/A 2212SN/A#if !FULL_SYSTEM 2221917SN/A thread.resize(number_of_threads); 2231917SN/A tids.resize(number_of_threads); 2241917SN/A#endif 2255529Snate@binkert.org 2265606Snate@binkert.org // The stages also need their CPU pointer setup. However this 2271917SN/A // must be done at the upper level CPU because they have pointers 2282356SN/A // to the upper level CPU, and not this FullO3CPU. 2295529Snate@binkert.org 2305606Snate@binkert.org // Set up Pointers to the activeThreads list for each stage 2315606Snate@binkert.org fetch.setActiveThreads(&activeThreads); 2325606Snate@binkert.org decode.setActiveThreads(&activeThreads); 2332356SN/A rename.setActiveThreads(&activeThreads); 2341917SN/A iew.setActiveThreads(&activeThreads); 2351917SN/A commit.setActiveThreads(&activeThreads); 2361917SN/A 2371917SN/A // Give each of the stages the time buffer they will use. 2382SN/A fetch.setTimeBuffer(&timeBuffer); 2392SN/A decode.setTimeBuffer(&timeBuffer); 240729SN/A rename.setTimeBuffer(&timeBuffer); 241707SN/A iew.setTimeBuffer(&timeBuffer); 242707SN/A commit.setTimeBuffer(&timeBuffer); 243707SN/A 244707SN/A // Also setup each of the stages' queues. 245707SN/A fetch.setFetchQueue(&fetchQueue); 246707SN/A decode.setFetchQueue(&fetchQueue); 2472680Sktlim@umich.edu commit.setFetchQueue(&fetchQueue); 2482SN/A decode.setDecodeQueue(&decodeQueue); 2492SN/A rename.setDecodeQueue(&decodeQueue); 2502SN/A rename.setRenameQueue(&renameQueue); 2512SN/A iew.setRenameQueue(&renameQueue); 2522680Sktlim@umich.edu iew.setIEWQueue(&iewQueue); 2532SN/A commit.setIEWQueue(&iewQueue); 2542SN/A commit.setRenameQueue(&renameQueue); 2552680Sktlim@umich.edu 2562190SN/A commit.setIEWStage(&iew); 2572190SN/A rename.setIEWStage(&iew); 2582190SN/A rename.setCommitStage(&commit); 2592SN/A 2602SN/A#if !FULL_SYSTEM 2613495Sktlim@umich.edu int active_threads = params->workload.size(); 2623495Sktlim@umich.edu 2633495Sktlim@umich.edu if (active_threads > Impl::MaxThreads) { 2643661Srdreslin@umich.edu panic("Workload Size too large. Increase the 'MaxThreads'" 2653495Sktlim@umich.edu "constant in your O3CPU impl. file (e.g. o3/alpha/impl.hh) or " 2663661Srdreslin@umich.edu "edit your workload size."); 2673495Sktlim@umich.edu } 2683495Sktlim@umich.edu#else 2693495Sktlim@umich.edu int active_threads = 1; 2703495Sktlim@umich.edu#endif 2713495Sktlim@umich.edu 2723495Sktlim@umich.edu //Make Sure That this a Valid Architeture 2733495Sktlim@umich.edu assert(params->numPhysIntRegs >= numThreads * TheISA::NumIntRegs); 2744599Sacolyte@umich.edu assert(params->numPhysFloatRegs >= numThreads * TheISA::NumFloatRegs); 2754599Sacolyte@umich.edu 2763661Srdreslin@umich.edu rename.setScoreboard(&scoreboard); 2773495Sktlim@umich.edu iew.setScoreboard(&scoreboard); 2783495Sktlim@umich.edu 2793495Sktlim@umich.edu // Setup the rename map for whichever stages need it. 2803495Sktlim@umich.edu PhysRegIndex lreg_idx = 0; 281180SN/A PhysRegIndex freg_idx = params->numPhysIntRegs; //Index to 1 after int regs 282180SN/A 2832680Sktlim@umich.edu for (int tid=0; tid < numThreads; tid++) { 284180SN/A bool bindRegs = (tid <= active_threads - 1); 2852680Sktlim@umich.edu 2862680Sktlim@umich.edu commitRenameMap[tid].init(TheISA::NumIntRegs, 2872378SN/A params->numPhysIntRegs, 2885714Shsul@eecs.umich.edu lreg_idx, //Index for Logical. Regs 2895713Shsul@eecs.umich.edu 2905714Shsul@eecs.umich.edu TheISA::NumFloatRegs, 291180SN/A params->numPhysFloatRegs, 292180SN/A freg_idx, //Index for Float Regs 293180SN/A 294180SN/A TheISA::NumMiscRegs, 295180SN/A 2964000Ssaidi@eecs.umich.edu TheISA::ZeroReg, 2974000Ssaidi@eecs.umich.edu TheISA::ZeroReg, 2984000Ssaidi@eecs.umich.edu 2994000Ssaidi@eecs.umich.edu tid, 3004000Ssaidi@eecs.umich.edu false); 3014000Ssaidi@eecs.umich.edu 3024000Ssaidi@eecs.umich.edu renameMap[tid].init(TheISA::NumIntRegs, 3034000Ssaidi@eecs.umich.edu params->numPhysIntRegs, 3044000Ssaidi@eecs.umich.edu lreg_idx, //Index for Logical. Regs 3054000Ssaidi@eecs.umich.edu 306180SN/A TheISA::NumFloatRegs, 3072798Sktlim@umich.edu params->numPhysFloatRegs, 308180SN/A freg_idx, //Index for Float Regs 3092359SN/A 3102359SN/A TheISA::NumMiscRegs, 3112359SN/A 3125606Snate@binkert.org TheISA::ZeroReg, 3132359SN/A TheISA::ZeroReg, 314180SN/A 315180SN/A tid, 316180SN/A bindRegs); 3174192Sktlim@umich.edu 318180SN/A activateThreadEvent[tid].init(tid, this); 3192680Sktlim@umich.edu deallocateContextEvent[tid].init(tid, this); 320180SN/A } 3215712Shsul@eecs.umich.edu 3225712Shsul@eecs.umich.edu rename.setRenameMap(renameMap); 3232680Sktlim@umich.edu commit.setRenameMap(commitRenameMap); 3242680Sktlim@umich.edu 3252680Sktlim@umich.edu // Give renameMap & rename stage access to the freeList; 326180SN/A for (int i=0; i < numThreads; i++) { 3272680Sktlim@umich.edu renameMap[i].setFreeList(&freeList); 3282651Ssaidi@eecs.umich.edu } 3292680Sktlim@umich.edu rename.setFreeList(&freeList); 3302651Ssaidi@eecs.umich.edu 3315714Shsul@eecs.umich.edu // Setup the ROB for whichever stages need it. 3325714Shsul@eecs.umich.edu commit.setROB(&rob); 3332359SN/A 3345217Ssaidi@eecs.umich.edu lastRunningCycle = curTick; 3355217Ssaidi@eecs.umich.edu 336180SN/A lastActivatedCycle = -1; 337605SN/A 3381858SN/A // Give renameMap & rename stage access to the freeList; 3393520Sgblack@eecs.umich.edu //for (int i=0; i < numThreads; i++) { 3402254SN/A //globalSeqNum[i] = 1; 3412680Sktlim@umich.edu //} 3422680Sktlim@umich.edu 3432254SN/A contextSwitch = false; 3444947Snate@binkert.org} 3455606Snate@binkert.org 346612SN/Atemplate <class Impl> 3474192Sktlim@umich.eduFullO3CPU<Impl>::~FullO3CPU() 3484192Sktlim@umich.edu{ 3494192Sktlim@umich.edu} 3504192Sktlim@umich.edu 3515476Snate@binkert.orgtemplate <class Impl> 3525476Snate@binkert.orgvoid 3534192Sktlim@umich.eduFullO3CPU<Impl>::fullCPURegStats() 3545476Snate@binkert.org{ 3554192Sktlim@umich.edu BaseO3CPU::regStats(); 3564192Sktlim@umich.edu 3575476Snate@binkert.org // Register any of the O3CPU's stats here. 3585476Snate@binkert.org timesIdled 3594192Sktlim@umich.edu .name(name() + ".timesIdled") 3605476Snate@binkert.org .desc("Number of times that the entire CPU went into an idle state and" 3614192Sktlim@umich.edu " unscheduled itself") 362180SN/A .prereq(timesIdled); 363180SN/A 364180SN/A idleCycles 3651858SN/A .name(name() + ".idleCycles") 3665536Srstrong@hp.com .desc("Total number of cycles that the CPU has spent unscheduled due " 3675606Snate@binkert.org "to idling") 3681917SN/A .prereq(idleCycles); 3691917SN/A 3701917SN/A // Number of Instructions simulated 3711917SN/A // -------------------------------- 3721917SN/A // Should probably be in Base CPU but need templated 3732680Sktlim@umich.edu // MaxThreads so put in here instead 3742680Sktlim@umich.edu committedInsts 3752680Sktlim@umich.edu .init(numThreads) 3761917SN/A .name(name() + ".committedInsts") 3772254SN/A .desc("Number of Instructions Simulated"); 3785606Snate@binkert.org 3791917SN/A totalCommittedInsts 3801917SN/A .name(name() + ".committedInsts_total") 3812SN/A .desc("Number of Instructions Simulated"); 3825704Snate@binkert.org 3832SN/A cpi 3845647Sgblack@eecs.umich.edu .name(name() + ".cpi") 3852SN/A .desc("CPI: Cycles Per Instruction") 3862SN/A .precision(6); 3872SN/A cpi = simTicks / committedInsts; 3885704Snate@binkert.org 3892SN/A totalCpi 3905647Sgblack@eecs.umich.edu .name(name() + ".cpi_total") 3912SN/A .desc("CPI: Total CPI of All Threads") 3922SN/A .precision(6); 3932SN/A totalCpi = simTicks / totalCommittedInsts; 3945704Snate@binkert.org 3952SN/A ipc 3965704Snate@binkert.org .name(name() + ".ipc") 3972SN/A .desc("IPC: Instructions Per Cycle") 3982SN/A .precision(6); 399921SN/A ipc = committedInsts / simTicks; 400921SN/A 401921SN/A totalIpc 4024000Ssaidi@eecs.umich.edu .name(name() + ".ipc_total") 4035647Sgblack@eecs.umich.edu .desc("IPC: Total IPC of All Threads") 404921SN/A .precision(6); 405921SN/A totalIpc = totalCommittedInsts / simTicks; 406921SN/A 407921SN/A} 408921SN/A 4094000Ssaidi@eecs.umich.edutemplate <class Impl> 4105647Sgblack@eecs.umich.eduPort * 411921SN/AFullO3CPU<Impl>::getPort(const std::string &if_name, int idx) 412921SN/A{ 4132SN/A if (if_name == "dcache_port") 4142SN/A return iew.getDcachePort(); 4151191SN/A else if (if_name == "icache_port") 4161191SN/A return fetch.getIcachePort(); 4171191SN/A else 4181191SN/A panic("No Such Port\n"); 4191191SN/A} 4201191SN/A 4211191SN/Atemplate <class Impl> 4221191SN/Avoid 4231191SN/AFullO3CPU<Impl>::tick() 4241191SN/A{ 4251191SN/A DPRINTF(O3CPU, "\n\nFullO3CPU: Ticking main, FullO3CPU.\n"); 4261191SN/A 4271191SN/A ++numCycles; 4281191SN/A 4291191SN/A// activity = false; 4301191SN/A 4311191SN/A //Tick each of the stages 4321191SN/A fetch.tick(); 4331191SN/A 4341191SN/A decode.tick(); 4351191SN/A 4361191SN/A rename.tick(); 4371191SN/A 4381191SN/A iew.tick(); 4391191SN/A 4401191SN/A commit.tick(); 441 442#if !FULL_SYSTEM 443 doContextSwitch(); 444#endif 445 446 // Now advance the time buffers 447 timeBuffer.advance(); 448 449 fetchQueue.advance(); 450 decodeQueue.advance(); 451 renameQueue.advance(); 452 iewQueue.advance(); 453 454 activityRec.advance(); 455 456 if (removeInstsThisCycle) { 457 cleanUpRemovedInsts(); 458 } 459 460 if (!tickEvent.scheduled()) { 461 if (_status == SwitchedOut || 462 getState() == SimObject::Drained) { 463 DPRINTF(O3CPU, "Switched out!\n"); 464 // increment stat 465 lastRunningCycle = curTick; 466 } else if (!activityRec.active() || _status == Idle) { 467 DPRINTF(O3CPU, "Idle!\n"); 468 lastRunningCycle = curTick; 469 timesIdled++; 470 } else { 471 tickEvent.schedule(nextCycle(curTick + cycles(1))); 472 DPRINTF(O3CPU, "Scheduling next tick!\n"); 473 } 474 } 475 476#if !FULL_SYSTEM 477 updateThreadPriority(); 478#endif 479 480} 481 482template <class Impl> 483void 484FullO3CPU<Impl>::init() 485{ 486 if (!deferRegistration) { 487 registerThreadContexts(); 488 } 489 490 // Set inSyscall so that the CPU doesn't squash when initially 491 // setting up registers. 492 for (int i = 0; i < number_of_threads; ++i) 493 thread[i]->inSyscall = true; 494 495 for (int tid=0; tid < number_of_threads; tid++) { 496#if FULL_SYSTEM 497 ThreadContext *src_tc = threadContexts[tid]; 498#else 499 ThreadContext *src_tc = thread[tid]->getTC(); 500#endif 501 // Threads start in the Suspended State 502 if (src_tc->status() != ThreadContext::Suspended) { 503 continue; 504 } 505 506#if FULL_SYSTEM 507 TheISA::initCPU(src_tc, src_tc->readCpuId()); 508#endif 509 } 510 511 // Clear inSyscall. 512 for (int i = 0; i < number_of_threads; ++i) 513 thread[i]->inSyscall = false; 514 515 // Initialize stages. 516 fetch.initStage(); 517 iew.initStage(); 518 rename.initStage(); 519 commit.initStage(); 520 521 commit.setThreads(thread); 522} 523 524template <class Impl> 525void 526FullO3CPU<Impl>::activateThread(unsigned tid) 527{ 528 list<unsigned>::iterator isActive = find( 529 activeThreads.begin(), activeThreads.end(), tid); 530 531 DPRINTF(O3CPU, "[tid:%i]: Calling activate thread.\n", tid); 532 533 if (isActive == activeThreads.end()) { 534 DPRINTF(O3CPU, "[tid:%i]: Adding to active threads list\n", 535 tid); 536 537 activeThreads.push_back(tid); 538 } 539} 540 541template <class Impl> 542void 543FullO3CPU<Impl>::deactivateThread(unsigned tid) 544{ 545 //Remove From Active List, if Active 546 list<unsigned>::iterator thread_it = 547 find(activeThreads.begin(), activeThreads.end(), tid); 548 549 DPRINTF(O3CPU, "[tid:%i]: Calling deactivate thread.\n", tid); 550 551 if (thread_it != activeThreads.end()) { 552 DPRINTF(O3CPU,"[tid:%i]: Removing from active threads list\n", 553 tid); 554 activeThreads.erase(thread_it); 555 } 556} 557 558template <class Impl> 559void 560FullO3CPU<Impl>::activateContext(int tid, int delay) 561{ 562 // Needs to set each stage to running as well. 563 if (delay){ 564 DPRINTF(O3CPU, "[tid:%i]: Scheduling thread context to activate " 565 "on cycle %d\n", tid, curTick + cycles(delay)); 566 scheduleActivateThreadEvent(tid, delay); 567 } else { 568 activateThread(tid); 569 } 570 571 if (lastActivatedCycle < curTick) { 572 scheduleTickEvent(delay); 573 574 // Be sure to signal that there's some activity so the CPU doesn't 575 // deschedule itself. 576 activityRec.activity(); 577 fetch.wakeFromQuiesce(); 578 579 lastActivatedCycle = curTick; 580 581 _status = Running; 582 } 583} 584 585template <class Impl> 586bool 587FullO3CPU<Impl>::deallocateContext(int tid, bool remove, int delay) 588{ 589 // Schedule removal of thread data from CPU 590 if (delay){ 591 DPRINTF(O3CPU, "[tid:%i]: Scheduling thread context to deallocate " 592 "on cycle %d\n", tid, curTick + cycles(delay)); 593 scheduleDeallocateContextEvent(tid, remove, delay); 594 return false; 595 } else { 596 deactivateThread(tid); 597 if (remove) 598 removeThread(tid); 599 return true; 600 } 601} 602 603template <class Impl> 604void 605FullO3CPU<Impl>::suspendContext(int tid) 606{ 607 DPRINTF(O3CPU,"[tid: %i]: Suspending Thread Context.\n", tid); 608 bool deallocated = deallocateContext(tid, false, 1); 609 // If this was the last thread then unschedule the tick event. 610 if (activeThreads.size() == 1 && !deallocated || 611 activeThreads.size() == 0) 612 unscheduleTickEvent(); 613 _status = Idle; 614} 615 616template <class Impl> 617void 618FullO3CPU<Impl>::haltContext(int tid) 619{ 620 //For now, this is the same as deallocate 621 DPRINTF(O3CPU,"[tid:%i]: Halt Context called. Deallocating", tid); 622 deallocateContext(tid, true, 1); 623} 624 625template <class Impl> 626void 627FullO3CPU<Impl>::insertThread(unsigned tid) 628{ 629 DPRINTF(O3CPU,"[tid:%i] Initializing thread into CPU"); 630 // Will change now that the PC and thread state is internal to the CPU 631 // and not in the ThreadContext. 632#if FULL_SYSTEM 633 ThreadContext *src_tc = system->threadContexts[tid]; 634#else 635 ThreadContext *src_tc = tcBase(tid); 636#endif 637 638 //Bind Int Regs to Rename Map 639 for (int ireg = 0; ireg < TheISA::NumIntRegs; ireg++) { 640 PhysRegIndex phys_reg = freeList.getIntReg(); 641 642 renameMap[tid].setEntry(ireg,phys_reg); 643 scoreboard.setReg(phys_reg); 644 } 645 646 //Bind Float Regs to Rename Map 647 for (int freg = 0; freg < TheISA::NumFloatRegs; freg++) { 648 PhysRegIndex phys_reg = freeList.getFloatReg(); 649 650 renameMap[tid].setEntry(freg,phys_reg); 651 scoreboard.setReg(phys_reg); 652 } 653 654 //Copy Thread Data Into RegFile 655 //this->copyFromTC(tid); 656 657 //Set PC/NPC/NNPC 658 setPC(src_tc->readPC(), tid); 659 setNextPC(src_tc->readNextPC(), tid); 660 setNextNPC(src_tc->readNextNPC(), tid); 661 662 src_tc->setStatus(ThreadContext::Active); 663 664 activateContext(tid,1); 665 666 //Reset ROB/IQ/LSQ Entries 667 commit.rob->resetEntries(); 668 iew.resetEntries(); 669} 670 671template <class Impl> 672void 673FullO3CPU<Impl>::removeThread(unsigned tid) 674{ 675 DPRINTF(O3CPU,"[tid:%i] Removing thread context from CPU.\n", tid); 676 677 // Copy Thread Data From RegFile 678 // If thread is suspended, it might be re-allocated 679 //this->copyToTC(tid); 680 681 // Unbind Int Regs from Rename Map 682 for (int ireg = 0; ireg < TheISA::NumIntRegs; ireg++) { 683 PhysRegIndex phys_reg = renameMap[tid].lookup(ireg); 684 685 scoreboard.unsetReg(phys_reg); 686 freeList.addReg(phys_reg); 687 } 688 689 // Unbind Float Regs from Rename Map 690 for (int freg = 0; freg < TheISA::NumFloatRegs; freg++) { 691 PhysRegIndex phys_reg = renameMap[tid].lookup(freg); 692 693 scoreboard.unsetReg(phys_reg); 694 freeList.addReg(phys_reg); 695 } 696 697 // Squash Throughout Pipeline 698 InstSeqNum squash_seq_num = commit.rob->readHeadInst(tid)->seqNum; 699 fetch.squash(0, sizeof(TheISA::MachInst), squash_seq_num, true, tid); 700 decode.squash(tid); 701 rename.squash(squash_seq_num, tid); 702 iew.squash(tid); 703 commit.rob->squash(squash_seq_num, tid); 704 705 assert(iew.ldstQueue.getCount(tid) == 0); 706 707 // Reset ROB/IQ/LSQ Entries 708 709 // Commented out for now. This should be possible to do by 710 // telling all the pipeline stages to drain first, and then 711 // checking until the drain completes. Once the pipeline is 712 // drained, call resetEntries(). - 10-09-06 ktlim 713/* 714 if (activeThreads.size() >= 1) { 715 commit.rob->resetEntries(); 716 iew.resetEntries(); 717 } 718*/ 719} 720 721 722template <class Impl> 723void 724FullO3CPU<Impl>::activateWhenReady(int tid) 725{ 726 DPRINTF(O3CPU,"[tid:%i]: Checking if resources are available for incoming" 727 "(e.g. PhysRegs/ROB/IQ/LSQ) \n", 728 tid); 729 730 bool ready = true; 731 732 if (freeList.numFreeIntRegs() >= TheISA::NumIntRegs) { 733 DPRINTF(O3CPU,"[tid:%i] Suspending thread due to not enough " 734 "Phys. Int. Regs.\n", 735 tid); 736 ready = false; 737 } else if (freeList.numFreeFloatRegs() >= TheISA::NumFloatRegs) { 738 DPRINTF(O3CPU,"[tid:%i] Suspending thread due to not enough " 739 "Phys. Float. Regs.\n", 740 tid); 741 ready = false; 742 } else if (commit.rob->numFreeEntries() >= 743 commit.rob->entryAmount(activeThreads.size() + 1)) { 744 DPRINTF(O3CPU,"[tid:%i] Suspending thread due to not enough " 745 "ROB entries.\n", 746 tid); 747 ready = false; 748 } else if (iew.instQueue.numFreeEntries() >= 749 iew.instQueue.entryAmount(activeThreads.size() + 1)) { 750 DPRINTF(O3CPU,"[tid:%i] Suspending thread due to not enough " 751 "IQ entries.\n", 752 tid); 753 ready = false; 754 } else if (iew.ldstQueue.numFreeEntries() >= 755 iew.ldstQueue.entryAmount(activeThreads.size() + 1)) { 756 DPRINTF(O3CPU,"[tid:%i] Suspending thread due to not enough " 757 "LSQ entries.\n", 758 tid); 759 ready = false; 760 } 761 762 if (ready) { 763 insertThread(tid); 764 765 contextSwitch = false; 766 767 cpuWaitList.remove(tid); 768 } else { 769 suspendContext(tid); 770 771 //blocks fetch 772 contextSwitch = true; 773 774 //@todo: dont always add to waitlist 775 //do waitlist 776 cpuWaitList.push_back(tid); 777 } 778} 779 780#if FULL_SYSTEM 781template <class Impl> 782void 783FullO3CPU<Impl>::updateMemPorts() 784{ 785 // Update all ThreadContext's memory ports (Functional/Virtual 786 // Ports) 787 for (int i = 0; i < thread.size(); ++i) 788 thread[i]->connectMemPorts(); 789} 790#endif 791 792template <class Impl> 793void 794FullO3CPU<Impl>::serialize(std::ostream &os) 795{ 796 SimObject::State so_state = SimObject::getState(); 797 SERIALIZE_ENUM(so_state); 798 BaseCPU::serialize(os); 799 nameOut(os, csprintf("%s.tickEvent", name())); 800 tickEvent.serialize(os); 801 802 // Use SimpleThread's ability to checkpoint to make it easier to 803 // write out the registers. Also make this static so it doesn't 804 // get instantiated multiple times (causes a panic in statistics). 805 static SimpleThread temp; 806 807 for (int i = 0; i < thread.size(); i++) { 808 nameOut(os, csprintf("%s.xc.%i", name(), i)); 809 temp.copyTC(thread[i]->getTC()); 810 temp.serialize(os); 811 } 812} 813 814template <class Impl> 815void 816FullO3CPU<Impl>::unserialize(Checkpoint *cp, const std::string §ion) 817{ 818 SimObject::State so_state; 819 UNSERIALIZE_ENUM(so_state); 820 BaseCPU::unserialize(cp, section); 821 tickEvent.unserialize(cp, csprintf("%s.tickEvent", section)); 822 823 // Use SimpleThread's ability to checkpoint to make it easier to 824 // read in the registers. Also make this static so it doesn't 825 // get instantiated multiple times (causes a panic in statistics). 826 static SimpleThread temp; 827 828 for (int i = 0; i < thread.size(); i++) { 829 temp.copyTC(thread[i]->getTC()); 830 temp.unserialize(cp, csprintf("%s.xc.%i", section, i)); 831 thread[i]->getTC()->copyArchRegs(temp.getTC()); 832 } 833} 834 835template <class Impl> 836unsigned int 837FullO3CPU<Impl>::drain(Event *drain_event) 838{ 839 DPRINTF(O3CPU, "Switching out\n"); 840 841 // If the CPU isn't doing anything, then return immediately. 842 if (_status == Idle || _status == SwitchedOut) { 843 return 0; 844 } 845 846 drainCount = 0; 847 fetch.drain(); 848 decode.drain(); 849 rename.drain(); 850 iew.drain(); 851 commit.drain(); 852 853 // Wake the CPU and record activity so everything can drain out if 854 // the CPU was not able to immediately drain. 855 if (getState() != SimObject::Drained) { 856 // A bit of a hack...set the drainEvent after all the drain() 857 // calls have been made, that way if all of the stages drain 858 // immediately, the signalDrained() function knows not to call 859 // process on the drain event. 860 drainEvent = drain_event; 861 862 wakeCPU(); 863 activityRec.activity(); 864 865 return 1; 866 } else { 867 return 0; 868 } 869} 870 871template <class Impl> 872void 873FullO3CPU<Impl>::resume() 874{ 875 fetch.resume(); 876 decode.resume(); 877 rename.resume(); 878 iew.resume(); 879 commit.resume(); 880 881 changeState(SimObject::Running); 882 883 if (_status == SwitchedOut || _status == Idle) 884 return; 885 886#if FULL_SYSTEM 887 assert(system->getMemoryMode() == System::Timing); 888#endif 889 890 if (!tickEvent.scheduled()) 891 tickEvent.schedule(nextCycle()); 892 _status = Running; 893} 894 895template <class Impl> 896void 897FullO3CPU<Impl>::signalDrained() 898{ 899 if (++drainCount == NumStages) { 900 if (tickEvent.scheduled()) 901 tickEvent.squash(); 902 903 changeState(SimObject::Drained); 904 905 BaseCPU::switchOut(); 906 907 if (drainEvent) { 908 drainEvent->process(); 909 drainEvent = NULL; 910 } 911 } 912 assert(drainCount <= 5); 913} 914 915template <class Impl> 916void 917FullO3CPU<Impl>::switchOut() 918{ 919 fetch.switchOut(); 920 rename.switchOut(); 921 iew.switchOut(); 922 commit.switchOut(); 923 instList.clear(); 924 while (!removeList.empty()) { 925 removeList.pop(); 926 } 927 928 _status = SwitchedOut; 929#if USE_CHECKER 930 if (checker) 931 checker->switchOut(); 932#endif 933 if (tickEvent.scheduled()) 934 tickEvent.squash(); 935} 936 937template <class Impl> 938void 939FullO3CPU<Impl>::takeOverFrom(BaseCPU *oldCPU) 940{ 941 // Flush out any old data from the time buffers. 942 for (int i = 0; i < timeBuffer.getSize(); ++i) { 943 timeBuffer.advance(); 944 fetchQueue.advance(); 945 decodeQueue.advance(); 946 renameQueue.advance(); 947 iewQueue.advance(); 948 } 949 950 activityRec.reset(); 951 952 BaseCPU::takeOverFrom(oldCPU, fetch.getIcachePort(), iew.getDcachePort()); 953 954 fetch.takeOverFrom(); 955 decode.takeOverFrom(); 956 rename.takeOverFrom(); 957 iew.takeOverFrom(); 958 commit.takeOverFrom(); 959 960 assert(!tickEvent.scheduled()); 961 962 // @todo: Figure out how to properly select the tid to put onto 963 // the active threads list. 964 int tid = 0; 965 966 list<unsigned>::iterator isActive = find( 967 activeThreads.begin(), activeThreads.end(), tid); 968 969 if (isActive == activeThreads.end()) { 970 //May Need to Re-code this if the delay variable is the delay 971 //needed for thread to activate 972 DPRINTF(O3CPU, "Adding Thread %i to active threads list\n", 973 tid); 974 975 activeThreads.push_back(tid); 976 } 977 978 // Set all statuses to active, schedule the CPU's tick event. 979 // @todo: Fix up statuses so this is handled properly 980 for (int i = 0; i < threadContexts.size(); ++i) { 981 ThreadContext *tc = threadContexts[i]; 982 if (tc->status() == ThreadContext::Active && _status != Running) { 983 _status = Running; 984 tickEvent.schedule(nextCycle()); 985 } 986 } 987 if (!tickEvent.scheduled()) 988 tickEvent.schedule(nextCycle()); 989} 990 991template <class Impl> 992uint64_t 993FullO3CPU<Impl>::readIntReg(int reg_idx) 994{ 995 return regFile.readIntReg(reg_idx); 996} 997 998template <class Impl> 999FloatReg 1000FullO3CPU<Impl>::readFloatReg(int reg_idx, int width) 1001{ 1002 return regFile.readFloatReg(reg_idx, width); 1003} 1004 1005template <class Impl> 1006FloatReg 1007FullO3CPU<Impl>::readFloatReg(int reg_idx) 1008{ 1009 return regFile.readFloatReg(reg_idx); 1010} 1011 1012template <class Impl> 1013FloatRegBits 1014FullO3CPU<Impl>::readFloatRegBits(int reg_idx, int width) 1015{ 1016 return regFile.readFloatRegBits(reg_idx, width); 1017} 1018 1019template <class Impl> 1020FloatRegBits 1021FullO3CPU<Impl>::readFloatRegBits(int reg_idx) 1022{ 1023 return regFile.readFloatRegBits(reg_idx); 1024} 1025 1026template <class Impl> 1027void 1028FullO3CPU<Impl>::setIntReg(int reg_idx, uint64_t val) 1029{ 1030 regFile.setIntReg(reg_idx, val); 1031} 1032 1033template <class Impl> 1034void 1035FullO3CPU<Impl>::setFloatReg(int reg_idx, FloatReg val, int width) 1036{ 1037 regFile.setFloatReg(reg_idx, val, width); 1038} 1039 1040template <class Impl> 1041void 1042FullO3CPU<Impl>::setFloatReg(int reg_idx, FloatReg val) 1043{ 1044 regFile.setFloatReg(reg_idx, val); 1045} 1046 1047template <class Impl> 1048void 1049FullO3CPU<Impl>::setFloatRegBits(int reg_idx, FloatRegBits val, int width) 1050{ 1051 regFile.setFloatRegBits(reg_idx, val, width); 1052} 1053 1054template <class Impl> 1055void 1056FullO3CPU<Impl>::setFloatRegBits(int reg_idx, FloatRegBits val) 1057{ 1058 regFile.setFloatRegBits(reg_idx, val); 1059} 1060 1061template <class Impl> 1062uint64_t 1063FullO3CPU<Impl>::readArchIntReg(int reg_idx, unsigned tid) 1064{ 1065 PhysRegIndex phys_reg = commitRenameMap[tid].lookup(reg_idx); 1066 1067 return regFile.readIntReg(phys_reg); 1068} 1069 1070template <class Impl> 1071float 1072FullO3CPU<Impl>::readArchFloatRegSingle(int reg_idx, unsigned tid) 1073{ 1074 int idx = reg_idx + TheISA::FP_Base_DepTag; 1075 PhysRegIndex phys_reg = commitRenameMap[tid].lookup(idx); 1076 1077 return regFile.readFloatReg(phys_reg); 1078} 1079 1080template <class Impl> 1081double 1082FullO3CPU<Impl>::readArchFloatRegDouble(int reg_idx, unsigned tid) 1083{ 1084 int idx = reg_idx + TheISA::FP_Base_DepTag; 1085 PhysRegIndex phys_reg = commitRenameMap[tid].lookup(idx); 1086 1087 return regFile.readFloatReg(phys_reg, 64); 1088} 1089 1090template <class Impl> 1091uint64_t 1092FullO3CPU<Impl>::readArchFloatRegInt(int reg_idx, unsigned tid) 1093{ 1094 int idx = reg_idx + TheISA::FP_Base_DepTag; 1095 PhysRegIndex phys_reg = commitRenameMap[tid].lookup(idx); 1096 1097 return regFile.readFloatRegBits(phys_reg); 1098} 1099 1100template <class Impl> 1101void 1102FullO3CPU<Impl>::setArchIntReg(int reg_idx, uint64_t val, unsigned tid) 1103{ 1104 PhysRegIndex phys_reg = commitRenameMap[tid].lookup(reg_idx); 1105 1106 regFile.setIntReg(phys_reg, val); 1107} 1108 1109template <class Impl> 1110void 1111FullO3CPU<Impl>::setArchFloatRegSingle(int reg_idx, float val, unsigned tid) 1112{ 1113 int idx = reg_idx + TheISA::FP_Base_DepTag; 1114 PhysRegIndex phys_reg = commitRenameMap[tid].lookup(idx); 1115 1116 regFile.setFloatReg(phys_reg, val); 1117} 1118 1119template <class Impl> 1120void 1121FullO3CPU<Impl>::setArchFloatRegDouble(int reg_idx, double val, unsigned tid) 1122{ 1123 int idx = reg_idx + TheISA::FP_Base_DepTag; 1124 PhysRegIndex phys_reg = commitRenameMap[tid].lookup(idx); 1125 1126 regFile.setFloatReg(phys_reg, val, 64); 1127} 1128 1129template <class Impl> 1130void 1131FullO3CPU<Impl>::setArchFloatRegInt(int reg_idx, uint64_t val, unsigned tid) 1132{ 1133 int idx = reg_idx + TheISA::FP_Base_DepTag; 1134 PhysRegIndex phys_reg = commitRenameMap[tid].lookup(idx); 1135 1136 regFile.setFloatRegBits(phys_reg, val); 1137} 1138 1139template <class Impl> 1140uint64_t 1141FullO3CPU<Impl>::readPC(unsigned tid) 1142{ 1143 return commit.readPC(tid); 1144} 1145 1146template <class Impl> 1147void 1148FullO3CPU<Impl>::setPC(Addr new_PC,unsigned tid) 1149{ 1150 commit.setPC(new_PC, tid); 1151} 1152 1153template <class Impl> 1154uint64_t 1155FullO3CPU<Impl>::readNextPC(unsigned tid) 1156{ 1157 return commit.readNextPC(tid); 1158} 1159 1160template <class Impl> 1161void 1162FullO3CPU<Impl>::setNextPC(uint64_t val,unsigned tid) 1163{ 1164 commit.setNextPC(val, tid); 1165} 1166 1167template <class Impl> 1168uint64_t 1169FullO3CPU<Impl>::readNextNPC(unsigned tid) 1170{ 1171 return commit.readNextNPC(tid); 1172} 1173 1174template <class Impl> 1175void 1176FullO3CPU<Impl>::setNextNPC(uint64_t val,unsigned tid) 1177{ 1178 commit.setNextNPC(val, tid); 1179} 1180 1181template <class Impl> 1182typename FullO3CPU<Impl>::ListIt 1183FullO3CPU<Impl>::addInst(DynInstPtr &inst) 1184{ 1185 instList.push_back(inst); 1186 1187 return --(instList.end()); 1188} 1189 1190template <class Impl> 1191void 1192FullO3CPU<Impl>::instDone(unsigned tid) 1193{ 1194 // Keep an instruction count. 1195 thread[tid]->numInst++; 1196 thread[tid]->numInsts++; 1197 committedInsts[tid]++; 1198 totalCommittedInsts++; 1199 1200 // Check for instruction-count-based events. 1201 comInstEventQueue[tid]->serviceEvents(thread[tid]->numInst); 1202} 1203 1204template <class Impl> 1205void 1206FullO3CPU<Impl>::addToRemoveList(DynInstPtr &inst) 1207{ 1208 removeInstsThisCycle = true; 1209 1210 removeList.push(inst->getInstListIt()); 1211} 1212 1213template <class Impl> 1214void 1215FullO3CPU<Impl>::removeFrontInst(DynInstPtr &inst) 1216{ 1217 DPRINTF(O3CPU, "Removing committed instruction [tid:%i] PC %#x " 1218 "[sn:%lli]\n", 1219 inst->threadNumber, inst->readPC(), inst->seqNum); 1220 1221 removeInstsThisCycle = true; 1222 1223 // Remove the front instruction. 1224 removeList.push(inst->getInstListIt()); 1225} 1226 1227template <class Impl> 1228void 1229FullO3CPU<Impl>::removeInstsNotInROB(unsigned tid, 1230 bool squash_delay_slot, 1231 const InstSeqNum &delay_slot_seq_num) 1232{ 1233 DPRINTF(O3CPU, "Thread %i: Deleting instructions from instruction" 1234 " list.\n", tid); 1235 1236 ListIt end_it; 1237 1238 bool rob_empty = false; 1239 1240 if (instList.empty()) { 1241 return; 1242 } else if (rob.isEmpty(/*tid*/)) { 1243 DPRINTF(O3CPU, "ROB is empty, squashing all insts.\n"); 1244 end_it = instList.begin(); 1245 rob_empty = true; 1246 } else { 1247 end_it = (rob.readTailInst(tid))->getInstListIt(); 1248 DPRINTF(O3CPU, "ROB is not empty, squashing insts not in ROB.\n"); 1249 } 1250 1251 removeInstsThisCycle = true; 1252 1253 ListIt inst_it = instList.end(); 1254 1255 inst_it--; 1256 1257 // Walk through the instruction list, removing any instructions 1258 // that were inserted after the given instruction iterator, end_it. 1259 while (inst_it != end_it) { 1260 assert(!instList.empty()); 1261 1262#if ISA_HAS_DELAY_SLOT 1263 if(!squash_delay_slot && 1264 delay_slot_seq_num >= (*inst_it)->seqNum) { 1265 break; 1266 } 1267#endif 1268 squashInstIt(inst_it, tid); 1269 1270 inst_it--; 1271 } 1272 1273 // If the ROB was empty, then we actually need to remove the first 1274 // instruction as well. 1275 if (rob_empty) { 1276 squashInstIt(inst_it, tid); 1277 } 1278} 1279 1280template <class Impl> 1281void 1282FullO3CPU<Impl>::removeInstsUntil(const InstSeqNum &seq_num, 1283 unsigned tid) 1284{ 1285 assert(!instList.empty()); 1286 1287 removeInstsThisCycle = true; 1288 1289 ListIt inst_iter = instList.end(); 1290 1291 inst_iter--; 1292 1293 DPRINTF(O3CPU, "Deleting instructions from instruction " 1294 "list that are from [tid:%i] and above [sn:%lli] (end=%lli).\n", 1295 tid, seq_num, (*inst_iter)->seqNum); 1296 1297 while ((*inst_iter)->seqNum > seq_num) { 1298 1299 bool break_loop = (inst_iter == instList.begin()); 1300 1301 squashInstIt(inst_iter, tid); 1302 1303 inst_iter--; 1304 1305 if (break_loop) 1306 break; 1307 } 1308} 1309 1310template <class Impl> 1311inline void 1312FullO3CPU<Impl>::squashInstIt(const ListIt &instIt, const unsigned &tid) 1313{ 1314 if ((*instIt)->threadNumber == tid) { 1315 DPRINTF(O3CPU, "Squashing instruction, " 1316 "[tid:%i] [sn:%lli] PC %#x\n", 1317 (*instIt)->threadNumber, 1318 (*instIt)->seqNum, 1319 (*instIt)->readPC()); 1320 1321 // Mark it as squashed. 1322 (*instIt)->setSquashed(); 1323 1324 // @todo: Formulate a consistent method for deleting 1325 // instructions from the instruction list 1326 // Remove the instruction from the list. 1327 removeList.push(instIt); 1328 } 1329} 1330 1331template <class Impl> 1332void 1333FullO3CPU<Impl>::cleanUpRemovedInsts() 1334{ 1335 while (!removeList.empty()) { 1336 DPRINTF(O3CPU, "Removing instruction, " 1337 "[tid:%i] [sn:%lli] PC %#x\n", 1338 (*removeList.front())->threadNumber, 1339 (*removeList.front())->seqNum, 1340 (*removeList.front())->readPC()); 1341 1342 instList.erase(removeList.front()); 1343 1344 removeList.pop(); 1345 } 1346 1347 removeInstsThisCycle = false; 1348} 1349/* 1350template <class Impl> 1351void 1352FullO3CPU<Impl>::removeAllInsts() 1353{ 1354 instList.clear(); 1355} 1356*/ 1357template <class Impl> 1358void 1359FullO3CPU<Impl>::dumpInsts() 1360{ 1361 int num = 0; 1362 1363 ListIt inst_list_it = instList.begin(); 1364 1365 cprintf("Dumping Instruction List\n"); 1366 1367 while (inst_list_it != instList.end()) { 1368 cprintf("Instruction:%i\nPC:%#x\n[tid:%i]\n[sn:%lli]\nIssued:%i\n" 1369 "Squashed:%i\n\n", 1370 num, (*inst_list_it)->readPC(), (*inst_list_it)->threadNumber, 1371 (*inst_list_it)->seqNum, (*inst_list_it)->isIssued(), 1372 (*inst_list_it)->isSquashed()); 1373 inst_list_it++; 1374 ++num; 1375 } 1376} 1377/* 1378template <class Impl> 1379void 1380FullO3CPU<Impl>::wakeDependents(DynInstPtr &inst) 1381{ 1382 iew.wakeDependents(inst); 1383} 1384*/ 1385template <class Impl> 1386void 1387FullO3CPU<Impl>::wakeCPU() 1388{ 1389 if (activityRec.active() || tickEvent.scheduled()) { 1390 DPRINTF(Activity, "CPU already running.\n"); 1391 return; 1392 } 1393 1394 DPRINTF(Activity, "Waking up CPU\n"); 1395 1396 idleCycles += (curTick - 1) - lastRunningCycle; 1397 1398 tickEvent.schedule(nextCycle()); 1399} 1400 1401template <class Impl> 1402int 1403FullO3CPU<Impl>::getFreeTid() 1404{ 1405 for (int i=0; i < numThreads; i++) { 1406 if (!tids[i]) { 1407 tids[i] = true; 1408 return i; 1409 } 1410 } 1411 1412 return -1; 1413} 1414 1415template <class Impl> 1416void 1417FullO3CPU<Impl>::doContextSwitch() 1418{ 1419 if (contextSwitch) { 1420 1421 //ADD CODE TO DEACTIVE THREAD HERE (???) 1422 1423 for (int tid=0; tid < cpuWaitList.size(); tid++) { 1424 activateWhenReady(tid); 1425 } 1426 1427 if (cpuWaitList.size() == 0) 1428 contextSwitch = true; 1429 } 1430} 1431 1432template <class Impl> 1433void 1434FullO3CPU<Impl>::updateThreadPriority() 1435{ 1436 if (activeThreads.size() > 1) 1437 { 1438 //DEFAULT TO ROUND ROBIN SCHEME 1439 //e.g. Move highest priority to end of thread list 1440 list<unsigned>::iterator list_begin = activeThreads.begin(); 1441 list<unsigned>::iterator list_end = activeThreads.end(); 1442 1443 unsigned high_thread = *list_begin; 1444 1445 activeThreads.erase(list_begin); 1446 1447 activeThreads.push_back(high_thread); 1448 } 1449} 1450 1451// Forward declaration of FullO3CPU. 1452template class FullO3CPU<O3CPUImpl>; 1453