cpu.cc revision 5640:c811ced9efc1
1/* 2 * Copyright (c) 2004-2006 The Regents of The University of Michigan 3 * All rights reserved. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions are 7 * met: redistributions of source code must retain the above copyright 8 * notice, this list of conditions and the following disclaimer; 9 * redistributions in binary form must reproduce the above copyright 10 * notice, this list of conditions and the following disclaimer in the 11 * documentation and/or other materials provided with the distribution; 12 * neither the name of the copyright holders nor the names of its 13 * contributors may be used to endorse or promote products derived from 14 * this software without specific prior written permission. 15 * 16 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 17 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 18 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 19 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 20 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 21 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 22 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 23 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 24 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 25 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 26 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 27 * 28 * Authors: Kevin Lim 29 * Korey Sewell 30 */ 31 32#include "config/full_system.hh" 33#include "config/use_checker.hh" 34 35#include "cpu/activity.hh" 36#include "cpu/simple_thread.hh" 37#include "cpu/thread_context.hh" 38#include "cpu/o3/isa_specific.hh" 39#include "cpu/o3/cpu.hh" 40#include "cpu/o3/thread_context.hh" 41#include "enums/MemoryMode.hh" 42#include "sim/core.hh" 43#include "sim/stat_control.hh" 44 45#if FULL_SYSTEM 46#include "cpu/quiesce_event.hh" 47#include "sim/system.hh" 48#else 49#include "sim/process.hh" 50#endif 51 52#if USE_CHECKER 53#include "cpu/checker/cpu.hh" 54#endif 55 56class BaseCPUParams; 57 58using namespace TheISA; 59 60BaseO3CPU::BaseO3CPU(BaseCPUParams *params) 61 : BaseCPU(params), cpu_id(0) 62{ 63} 64 65void 66BaseO3CPU::regStats() 67{ 68 BaseCPU::regStats(); 69} 70 71template <class Impl> 72FullO3CPU<Impl>::TickEvent::TickEvent(FullO3CPU<Impl> *c) 73 : Event(CPU_Tick_Pri), cpu(c) 74{ 75} 76 77template <class Impl> 78void 79FullO3CPU<Impl>::TickEvent::process() 80{ 81 cpu->tick(); 82} 83 84template <class Impl> 85const char * 86FullO3CPU<Impl>::TickEvent::description() const 87{ 88 return "FullO3CPU tick"; 89} 90 91template <class Impl> 92FullO3CPU<Impl>::ActivateThreadEvent::ActivateThreadEvent() 93 : Event(CPU_Switch_Pri) 94{ 95} 96 97template <class Impl> 98void 99FullO3CPU<Impl>::ActivateThreadEvent::init(int thread_num, 100 FullO3CPU<Impl> *thread_cpu) 101{ 102 tid = thread_num; 103 cpu = thread_cpu; 104} 105 106template <class Impl> 107void 108FullO3CPU<Impl>::ActivateThreadEvent::process() 109{ 110 cpu->activateThread(tid); 111} 112 113template <class Impl> 114const char * 115FullO3CPU<Impl>::ActivateThreadEvent::description() const 116{ 117 return "FullO3CPU \"Activate Thread\""; 118} 119 120template <class Impl> 121FullO3CPU<Impl>::DeallocateContextEvent::DeallocateContextEvent() 122 : Event(CPU_Tick_Pri), tid(0), remove(false), cpu(NULL) 123{ 124} 125 126template <class Impl> 127void 128FullO3CPU<Impl>::DeallocateContextEvent::init(int thread_num, 129 FullO3CPU<Impl> *thread_cpu) 130{ 131 tid = thread_num; 132 cpu = thread_cpu; 133 remove = false; 134} 135 136template <class Impl> 137void 138FullO3CPU<Impl>::DeallocateContextEvent::process() 139{ 140 cpu->deactivateThread(tid); 141 if (remove) 142 cpu->removeThread(tid); 143} 144 145template <class Impl> 146const char * 147FullO3CPU<Impl>::DeallocateContextEvent::description() const 148{ 149 return "FullO3CPU \"Deallocate Context\""; 150} 151 152template <class Impl> 153FullO3CPU<Impl>::FullO3CPU(DerivO3CPUParams *params) 154 : BaseO3CPU(params), 155 itb(params->itb), 156 dtb(params->dtb), 157 tickEvent(this), 158 removeInstsThisCycle(false), 159 fetch(this, params), 160 decode(this, params), 161 rename(this, params), 162 iew(this, params), 163 commit(this, params), 164 165 regFile(this, params->numPhysIntRegs, 166 params->numPhysFloatRegs), 167 168 freeList(params->numThreads, 169 TheISA::NumIntRegs, params->numPhysIntRegs, 170 TheISA::NumFloatRegs, params->numPhysFloatRegs), 171 172 rob(this, 173 params->numROBEntries, params->squashWidth, 174 params->smtROBPolicy, params->smtROBThreshold, 175 params->numThreads), 176 177 scoreboard(params->numThreads, 178 TheISA::NumIntRegs, params->numPhysIntRegs, 179 TheISA::NumFloatRegs, params->numPhysFloatRegs, 180 TheISA::NumMiscRegs * number_of_threads, 181 TheISA::ZeroReg), 182 183 timeBuffer(params->backComSize, params->forwardComSize), 184 fetchQueue(params->backComSize, params->forwardComSize), 185 decodeQueue(params->backComSize, params->forwardComSize), 186 renameQueue(params->backComSize, params->forwardComSize), 187 iewQueue(params->backComSize, params->forwardComSize), 188 activityRec(NumStages, 189 params->backComSize + params->forwardComSize, 190 params->activity), 191 192 globalSeqNum(1), 193#if FULL_SYSTEM 194 system(params->system), 195 physmem(system->physmem), 196#endif // FULL_SYSTEM 197 drainCount(0), 198 deferRegistration(params->defer_registration), 199 numThreads(number_of_threads) 200{ 201 if (!deferRegistration) { 202 _status = Running; 203 } else { 204 _status = Idle; 205 } 206 207#if USE_CHECKER 208 if (params->checker) { 209 BaseCPU *temp_checker = params->checker; 210 checker = dynamic_cast<Checker<DynInstPtr> *>(temp_checker); 211#if FULL_SYSTEM 212 checker->setSystem(params->system); 213#endif 214 } else { 215 checker = NULL; 216 } 217#endif // USE_CHECKER 218 219#if !FULL_SYSTEM 220 thread.resize(number_of_threads); 221 tids.resize(number_of_threads); 222#endif 223 224 // The stages also need their CPU pointer setup. However this 225 // must be done at the upper level CPU because they have pointers 226 // to the upper level CPU, and not this FullO3CPU. 227 228 // Set up Pointers to the activeThreads list for each stage 229 fetch.setActiveThreads(&activeThreads); 230 decode.setActiveThreads(&activeThreads); 231 rename.setActiveThreads(&activeThreads); 232 iew.setActiveThreads(&activeThreads); 233 commit.setActiveThreads(&activeThreads); 234 235 // Give each of the stages the time buffer they will use. 236 fetch.setTimeBuffer(&timeBuffer); 237 decode.setTimeBuffer(&timeBuffer); 238 rename.setTimeBuffer(&timeBuffer); 239 iew.setTimeBuffer(&timeBuffer); 240 commit.setTimeBuffer(&timeBuffer); 241 242 // Also setup each of the stages' queues. 243 fetch.setFetchQueue(&fetchQueue); 244 decode.setFetchQueue(&fetchQueue); 245 commit.setFetchQueue(&fetchQueue); 246 decode.setDecodeQueue(&decodeQueue); 247 rename.setDecodeQueue(&decodeQueue); 248 rename.setRenameQueue(&renameQueue); 249 iew.setRenameQueue(&renameQueue); 250 iew.setIEWQueue(&iewQueue); 251 commit.setIEWQueue(&iewQueue); 252 commit.setRenameQueue(&renameQueue); 253 254 commit.setIEWStage(&iew); 255 rename.setIEWStage(&iew); 256 rename.setCommitStage(&commit); 257 258#if !FULL_SYSTEM 259 int active_threads = params->workload.size(); 260 261 if (active_threads > Impl::MaxThreads) { 262 panic("Workload Size too large. Increase the 'MaxThreads'" 263 "constant in your O3CPU impl. file (e.g. o3/alpha/impl.hh) or " 264 "edit your workload size."); 265 } 266#else 267 int active_threads = 1; 268#endif 269 270 //Make Sure That this a Valid Architeture 271 assert(params->numPhysIntRegs >= numThreads * TheISA::NumIntRegs); 272 assert(params->numPhysFloatRegs >= numThreads * TheISA::NumFloatRegs); 273 274 rename.setScoreboard(&scoreboard); 275 iew.setScoreboard(&scoreboard); 276 277 // Setup the rename map for whichever stages need it. 278 PhysRegIndex lreg_idx = 0; 279 PhysRegIndex freg_idx = params->numPhysIntRegs; //Index to 1 after int regs 280 281 for (int tid=0; tid < numThreads; tid++) { 282 bool bindRegs = (tid <= active_threads - 1); 283 284 commitRenameMap[tid].init(TheISA::NumIntRegs, 285 params->numPhysIntRegs, 286 lreg_idx, //Index for Logical. Regs 287 288 TheISA::NumFloatRegs, 289 params->numPhysFloatRegs, 290 freg_idx, //Index for Float Regs 291 292 TheISA::NumMiscRegs, 293 294 TheISA::ZeroReg, 295 TheISA::ZeroReg, 296 297 tid, 298 false); 299 300 renameMap[tid].init(TheISA::NumIntRegs, 301 params->numPhysIntRegs, 302 lreg_idx, //Index for Logical. Regs 303 304 TheISA::NumFloatRegs, 305 params->numPhysFloatRegs, 306 freg_idx, //Index for Float Regs 307 308 TheISA::NumMiscRegs, 309 310 TheISA::ZeroReg, 311 TheISA::ZeroReg, 312 313 tid, 314 bindRegs); 315 316 activateThreadEvent[tid].init(tid, this); 317 deallocateContextEvent[tid].init(tid, this); 318 } 319 320 rename.setRenameMap(renameMap); 321 commit.setRenameMap(commitRenameMap); 322 323 // Give renameMap & rename stage access to the freeList; 324 for (int i=0; i < numThreads; i++) { 325 renameMap[i].setFreeList(&freeList); 326 } 327 rename.setFreeList(&freeList); 328 329 // Setup the ROB for whichever stages need it. 330 commit.setROB(&rob); 331 332 lastRunningCycle = curTick; 333 334 lastActivatedCycle = -1; 335 336 // Give renameMap & rename stage access to the freeList; 337 //for (int i=0; i < numThreads; i++) { 338 //globalSeqNum[i] = 1; 339 //} 340 341 contextSwitch = false; 342 DPRINTF(O3CPU, "Creating O3CPU object.\n"); 343 344 // Setup any thread state. 345 this->thread.resize(this->numThreads); 346 347 for (int i = 0; i < this->numThreads; ++i) { 348#if FULL_SYSTEM 349 // SMT is not supported in FS mode yet. 350 assert(this->numThreads == 1); 351 this->thread[i] = new Thread(this, 0); 352 this->thread[i]->setStatus(ThreadContext::Suspended); 353#else 354 if (i < params->workload.size()) { 355 DPRINTF(O3CPU, "Workload[%i] process is %#x", 356 i, this->thread[i]); 357 this->thread[i] = new typename FullO3CPU<Impl>::Thread( 358 (typename Impl::O3CPU *)(this), 359 i, params->workload[i], i); 360 361 this->thread[i]->setStatus(ThreadContext::Suspended); 362 363 //usedTids[i] = true; 364 //threadMap[i] = i; 365 } else { 366 //Allocate Empty thread so M5 can use later 367 //when scheduling threads to CPU 368 Process* dummy_proc = NULL; 369 370 this->thread[i] = new typename FullO3CPU<Impl>::Thread( 371 (typename Impl::O3CPU *)(this), 372 i, dummy_proc, i); 373 //usedTids[i] = false; 374 } 375#endif // !FULL_SYSTEM 376 377 ThreadContext *tc; 378 379 // Setup the TC that will serve as the interface to the threads/CPU. 380 O3ThreadContext<Impl> *o3_tc = new O3ThreadContext<Impl>; 381 382 tc = o3_tc; 383 384 // If we're using a checker, then the TC should be the 385 // CheckerThreadContext. 386#if USE_CHECKER 387 if (params->checker) { 388 tc = new CheckerThreadContext<O3ThreadContext<Impl> >( 389 o3_tc, this->checker); 390 } 391#endif 392 393 o3_tc->cpu = (typename Impl::O3CPU *)(this); 394 assert(o3_tc->cpu); 395 o3_tc->thread = this->thread[i]; 396 397#if FULL_SYSTEM 398 // Setup quiesce event. 399 this->thread[i]->quiesceEvent = new EndQuiesceEvent(tc); 400#endif 401 // Give the thread the TC. 402 this->thread[i]->tc = tc; 403 this->thread[i]->setCpuId(params->cpu_id); 404 405 // Add the TC to the CPU's list of TC's. 406 this->threadContexts.push_back(tc); 407 } 408 409 for (int i=0; i < this->numThreads; i++) { 410 this->thread[i]->setFuncExeInst(0); 411 } 412 413 lockAddr = 0; 414 lockFlag = false; 415} 416 417#if !FULL_SYSTEM 418 419template <class Impl> 420TheISA::IntReg 421FullO3CPU<Impl>::getSyscallArg(int i, int tid) 422{ 423 assert(i < TheISA::NumArgumentRegs); 424 TheISA::IntReg idx = TheISA::flattenIntIndex(this->tcBase(tid), 425 TheISA::ArgumentReg[i]); 426 TheISA::IntReg val = this->readArchIntReg(idx, tid); 427#if THE_ISA == SPARC_ISA 428 if (bits(this->readMiscRegNoEffect(SparcISA::MISCREG_PSTATE, tid), 3, 3)) 429 val = bits(val, 31, 0); 430#endif 431 return val; 432} 433 434template <class Impl> 435void 436FullO3CPU<Impl>::setSyscallArg(int i, TheISA::IntReg val, int tid) 437{ 438 assert(i < TheISA::NumArgumentRegs); 439 TheISA::IntReg idx = TheISA::flattenIntIndex(this->tcBase(tid), 440 TheISA::ArgumentReg[i]); 441 this->setArchIntReg(idx, val, tid); 442} 443#endif 444 445template <class Impl> 446FullO3CPU<Impl>::~FullO3CPU() 447{ 448} 449 450template <class Impl> 451void 452FullO3CPU<Impl>::regStats() 453{ 454 BaseO3CPU::regStats(); 455 456 // Register any of the O3CPU's stats here. 457 timesIdled 458 .name(name() + ".timesIdled") 459 .desc("Number of times that the entire CPU went into an idle state and" 460 " unscheduled itself") 461 .prereq(timesIdled); 462 463 idleCycles 464 .name(name() + ".idleCycles") 465 .desc("Total number of cycles that the CPU has spent unscheduled due " 466 "to idling") 467 .prereq(idleCycles); 468 469 // Number of Instructions simulated 470 // -------------------------------- 471 // Should probably be in Base CPU but need templated 472 // MaxThreads so put in here instead 473 committedInsts 474 .init(numThreads) 475 .name(name() + ".committedInsts") 476 .desc("Number of Instructions Simulated"); 477 478 totalCommittedInsts 479 .name(name() + ".committedInsts_total") 480 .desc("Number of Instructions Simulated"); 481 482 cpi 483 .name(name() + ".cpi") 484 .desc("CPI: Cycles Per Instruction") 485 .precision(6); 486 cpi = numCycles / committedInsts; 487 488 totalCpi 489 .name(name() + ".cpi_total") 490 .desc("CPI: Total CPI of All Threads") 491 .precision(6); 492 totalCpi = numCycles / totalCommittedInsts; 493 494 ipc 495 .name(name() + ".ipc") 496 .desc("IPC: Instructions Per Cycle") 497 .precision(6); 498 ipc = committedInsts / numCycles; 499 500 totalIpc 501 .name(name() + ".ipc_total") 502 .desc("IPC: Total IPC of All Threads") 503 .precision(6); 504 totalIpc = totalCommittedInsts / numCycles; 505 506 this->fetch.regStats(); 507 this->decode.regStats(); 508 this->rename.regStats(); 509 this->iew.regStats(); 510 this->commit.regStats(); 511} 512 513template <class Impl> 514Port * 515FullO3CPU<Impl>::getPort(const std::string &if_name, int idx) 516{ 517 if (if_name == "dcache_port") 518 return iew.getDcachePort(); 519 else if (if_name == "icache_port") 520 return fetch.getIcachePort(); 521 else 522 panic("No Such Port\n"); 523} 524 525template <class Impl> 526void 527FullO3CPU<Impl>::tick() 528{ 529 DPRINTF(O3CPU, "\n\nFullO3CPU: Ticking main, FullO3CPU.\n"); 530 531 ++numCycles; 532 533// activity = false; 534 535 //Tick each of the stages 536 fetch.tick(); 537 538 decode.tick(); 539 540 rename.tick(); 541 542 iew.tick(); 543 544 commit.tick(); 545 546#if !FULL_SYSTEM 547 doContextSwitch(); 548#endif 549 550 // Now advance the time buffers 551 timeBuffer.advance(); 552 553 fetchQueue.advance(); 554 decodeQueue.advance(); 555 renameQueue.advance(); 556 iewQueue.advance(); 557 558 activityRec.advance(); 559 560 if (removeInstsThisCycle) { 561 cleanUpRemovedInsts(); 562 } 563 564 if (!tickEvent.scheduled()) { 565 if (_status == SwitchedOut || 566 getState() == SimObject::Drained) { 567 DPRINTF(O3CPU, "Switched out!\n"); 568 // increment stat 569 lastRunningCycle = curTick; 570 } else if (!activityRec.active() || _status == Idle) { 571 DPRINTF(O3CPU, "Idle!\n"); 572 lastRunningCycle = curTick; 573 timesIdled++; 574 } else { 575 schedule(tickEvent, nextCycle(curTick + ticks(1))); 576 DPRINTF(O3CPU, "Scheduling next tick!\n"); 577 } 578 } 579 580#if !FULL_SYSTEM 581 updateThreadPriority(); 582#endif 583} 584 585template <class Impl> 586void 587FullO3CPU<Impl>::init() 588{ 589 if (!deferRegistration) { 590 registerThreadContexts(); 591 } 592 593 // Set inSyscall so that the CPU doesn't squash when initially 594 // setting up registers. 595 for (int i = 0; i < number_of_threads; ++i) 596 thread[i]->inSyscall = true; 597 598 for (int tid=0; tid < number_of_threads; tid++) { 599#if FULL_SYSTEM 600 ThreadContext *src_tc = threadContexts[tid]; 601#else 602 ThreadContext *src_tc = thread[tid]->getTC(); 603#endif 604 // Threads start in the Suspended State 605 if (src_tc->status() != ThreadContext::Suspended) { 606 continue; 607 } 608 609#if FULL_SYSTEM 610 TheISA::initCPU(src_tc, src_tc->readCpuId()); 611#endif 612 } 613 614 // Clear inSyscall. 615 for (int i = 0; i < number_of_threads; ++i) 616 thread[i]->inSyscall = false; 617 618 // Initialize stages. 619 fetch.initStage(); 620 iew.initStage(); 621 rename.initStage(); 622 commit.initStage(); 623 624 commit.setThreads(thread); 625} 626 627template <class Impl> 628void 629FullO3CPU<Impl>::activateThread(unsigned tid) 630{ 631 std::list<unsigned>::iterator isActive = 632 std::find(activeThreads.begin(), activeThreads.end(), tid); 633 634 DPRINTF(O3CPU, "[tid:%i]: Calling activate thread.\n", tid); 635 636 if (isActive == activeThreads.end()) { 637 DPRINTF(O3CPU, "[tid:%i]: Adding to active threads list\n", 638 tid); 639 640 activeThreads.push_back(tid); 641 } 642} 643 644template <class Impl> 645void 646FullO3CPU<Impl>::deactivateThread(unsigned tid) 647{ 648 //Remove From Active List, if Active 649 std::list<unsigned>::iterator thread_it = 650 std::find(activeThreads.begin(), activeThreads.end(), tid); 651 652 DPRINTF(O3CPU, "[tid:%i]: Calling deactivate thread.\n", tid); 653 654 if (thread_it != activeThreads.end()) { 655 DPRINTF(O3CPU,"[tid:%i]: Removing from active threads list\n", 656 tid); 657 activeThreads.erase(thread_it); 658 } 659} 660 661template <class Impl> 662void 663FullO3CPU<Impl>::activateContext(int tid, int delay) 664{ 665 // Needs to set each stage to running as well. 666 if (delay){ 667 DPRINTF(O3CPU, "[tid:%i]: Scheduling thread context to activate " 668 "on cycle %d\n", tid, curTick + ticks(delay)); 669 scheduleActivateThreadEvent(tid, delay); 670 } else { 671 activateThread(tid); 672 } 673 674 if (lastActivatedCycle < curTick) { 675 scheduleTickEvent(delay); 676 677 // Be sure to signal that there's some activity so the CPU doesn't 678 // deschedule itself. 679 activityRec.activity(); 680 fetch.wakeFromQuiesce(); 681 682 lastActivatedCycle = curTick; 683 684 _status = Running; 685 } 686} 687 688template <class Impl> 689bool 690FullO3CPU<Impl>::deallocateContext(int tid, bool remove, int delay) 691{ 692 // Schedule removal of thread data from CPU 693 if (delay){ 694 DPRINTF(O3CPU, "[tid:%i]: Scheduling thread context to deallocate " 695 "on cycle %d\n", tid, curTick + ticks(delay)); 696 scheduleDeallocateContextEvent(tid, remove, delay); 697 return false; 698 } else { 699 deactivateThread(tid); 700 if (remove) 701 removeThread(tid); 702 return true; 703 } 704} 705 706template <class Impl> 707void 708FullO3CPU<Impl>::suspendContext(int tid) 709{ 710 DPRINTF(O3CPU,"[tid: %i]: Suspending Thread Context.\n", tid); 711 bool deallocated = deallocateContext(tid, false, 1); 712 // If this was the last thread then unschedule the tick event. 713 if ((activeThreads.size() == 1 && !deallocated) || 714 activeThreads.size() == 0) 715 unscheduleTickEvent(); 716 _status = Idle; 717} 718 719template <class Impl> 720void 721FullO3CPU<Impl>::haltContext(int tid) 722{ 723 //For now, this is the same as deallocate 724 DPRINTF(O3CPU,"[tid:%i]: Halt Context called. Deallocating", tid); 725 deallocateContext(tid, true, 1); 726} 727 728template <class Impl> 729void 730FullO3CPU<Impl>::insertThread(unsigned tid) 731{ 732 DPRINTF(O3CPU,"[tid:%i] Initializing thread into CPU"); 733 // Will change now that the PC and thread state is internal to the CPU 734 // and not in the ThreadContext. 735#if FULL_SYSTEM 736 ThreadContext *src_tc = system->threadContexts[tid]; 737#else 738 ThreadContext *src_tc = tcBase(tid); 739#endif 740 741 //Bind Int Regs to Rename Map 742 for (int ireg = 0; ireg < TheISA::NumIntRegs; ireg++) { 743 PhysRegIndex phys_reg = freeList.getIntReg(); 744 745 renameMap[tid].setEntry(ireg,phys_reg); 746 scoreboard.setReg(phys_reg); 747 } 748 749 //Bind Float Regs to Rename Map 750 for (int freg = 0; freg < TheISA::NumFloatRegs; freg++) { 751 PhysRegIndex phys_reg = freeList.getFloatReg(); 752 753 renameMap[tid].setEntry(freg,phys_reg); 754 scoreboard.setReg(phys_reg); 755 } 756 757 //Copy Thread Data Into RegFile 758 //this->copyFromTC(tid); 759 760 //Set PC/NPC/NNPC 761 setPC(src_tc->readPC(), tid); 762 setNextPC(src_tc->readNextPC(), tid); 763 setNextNPC(src_tc->readNextNPC(), tid); 764 765 src_tc->setStatus(ThreadContext::Active); 766 767 activateContext(tid,1); 768 769 //Reset ROB/IQ/LSQ Entries 770 commit.rob->resetEntries(); 771 iew.resetEntries(); 772} 773 774template <class Impl> 775void 776FullO3CPU<Impl>::removeThread(unsigned tid) 777{ 778 DPRINTF(O3CPU,"[tid:%i] Removing thread context from CPU.\n", tid); 779 780 // Copy Thread Data From RegFile 781 // If thread is suspended, it might be re-allocated 782 // this->copyToTC(tid); 783 784 785 // @todo: 2-27-2008: Fix how we free up rename mappings 786 // here to alleviate the case for double-freeing registers 787 // in SMT workloads. 788 789 // Unbind Int Regs from Rename Map 790 for (int ireg = 0; ireg < TheISA::NumIntRegs; ireg++) { 791 PhysRegIndex phys_reg = renameMap[tid].lookup(ireg); 792 793 scoreboard.unsetReg(phys_reg); 794 freeList.addReg(phys_reg); 795 } 796 797 // Unbind Float Regs from Rename Map 798 for (int freg = TheISA::NumIntRegs; freg < TheISA::NumFloatRegs; freg++) { 799 PhysRegIndex phys_reg = renameMap[tid].lookup(freg); 800 801 scoreboard.unsetReg(phys_reg); 802 freeList.addReg(phys_reg); 803 } 804 805 // Squash Throughout Pipeline 806 InstSeqNum squash_seq_num = commit.rob->readHeadInst(tid)->seqNum; 807 fetch.squash(0, sizeof(TheISA::MachInst), 0, squash_seq_num, tid); 808 decode.squash(tid); 809 rename.squash(squash_seq_num, tid); 810 iew.squash(tid); 811 iew.ldstQueue.squash(squash_seq_num, tid); 812 commit.rob->squash(squash_seq_num, tid); 813 814 815 assert(iew.instQueue.getCount(tid) == 0); 816 assert(iew.ldstQueue.getCount(tid) == 0); 817 818 // Reset ROB/IQ/LSQ Entries 819 820 // Commented out for now. This should be possible to do by 821 // telling all the pipeline stages to drain first, and then 822 // checking until the drain completes. Once the pipeline is 823 // drained, call resetEntries(). - 10-09-06 ktlim 824/* 825 if (activeThreads.size() >= 1) { 826 commit.rob->resetEntries(); 827 iew.resetEntries(); 828 } 829*/ 830} 831 832 833template <class Impl> 834void 835FullO3CPU<Impl>::activateWhenReady(int tid) 836{ 837 DPRINTF(O3CPU,"[tid:%i]: Checking if resources are available for incoming" 838 "(e.g. PhysRegs/ROB/IQ/LSQ) \n", 839 tid); 840 841 bool ready = true; 842 843 if (freeList.numFreeIntRegs() >= TheISA::NumIntRegs) { 844 DPRINTF(O3CPU,"[tid:%i] Suspending thread due to not enough " 845 "Phys. Int. Regs.\n", 846 tid); 847 ready = false; 848 } else if (freeList.numFreeFloatRegs() >= TheISA::NumFloatRegs) { 849 DPRINTF(O3CPU,"[tid:%i] Suspending thread due to not enough " 850 "Phys. Float. Regs.\n", 851 tid); 852 ready = false; 853 } else if (commit.rob->numFreeEntries() >= 854 commit.rob->entryAmount(activeThreads.size() + 1)) { 855 DPRINTF(O3CPU,"[tid:%i] Suspending thread due to not enough " 856 "ROB entries.\n", 857 tid); 858 ready = false; 859 } else if (iew.instQueue.numFreeEntries() >= 860 iew.instQueue.entryAmount(activeThreads.size() + 1)) { 861 DPRINTF(O3CPU,"[tid:%i] Suspending thread due to not enough " 862 "IQ entries.\n", 863 tid); 864 ready = false; 865 } else if (iew.ldstQueue.numFreeEntries() >= 866 iew.ldstQueue.entryAmount(activeThreads.size() + 1)) { 867 DPRINTF(O3CPU,"[tid:%i] Suspending thread due to not enough " 868 "LSQ entries.\n", 869 tid); 870 ready = false; 871 } 872 873 if (ready) { 874 insertThread(tid); 875 876 contextSwitch = false; 877 878 cpuWaitList.remove(tid); 879 } else { 880 suspendContext(tid); 881 882 //blocks fetch 883 contextSwitch = true; 884 885 //@todo: dont always add to waitlist 886 //do waitlist 887 cpuWaitList.push_back(tid); 888 } 889} 890 891#if FULL_SYSTEM 892template <class Impl> 893void 894FullO3CPU<Impl>::post_interrupt(int int_num, int index) 895{ 896 BaseCPU::post_interrupt(int_num, index); 897 898 if (this->thread[0]->status() == ThreadContext::Suspended) { 899 DPRINTF(IPI,"Suspended Processor awoke\n"); 900 this->threadContexts[0]->activate(); 901 } 902} 903 904template <class Impl> 905Fault 906FullO3CPU<Impl>::getInterrupts() 907{ 908 // Check if there are any outstanding interrupts 909 return this->interrupts.getInterrupt(this->threadContexts[0]); 910} 911 912template <class Impl> 913void 914FullO3CPU<Impl>::processInterrupts(Fault interrupt) 915{ 916 // Check for interrupts here. For now can copy the code that 917 // exists within isa_fullsys_traits.hh. Also assume that thread 0 918 // is the one that handles the interrupts. 919 // @todo: Possibly consolidate the interrupt checking code. 920 // @todo: Allow other threads to handle interrupts. 921 922 assert(interrupt != NoFault); 923 this->interrupts.updateIntrInfo(this->threadContexts[0]); 924 925 DPRINTF(O3CPU, "Interrupt %s being handled\n", interrupt->name()); 926 this->trap(interrupt, 0); 927} 928 929template <class Impl> 930void 931FullO3CPU<Impl>::updateMemPorts() 932{ 933 // Update all ThreadContext's memory ports (Functional/Virtual 934 // Ports) 935 for (int i = 0; i < thread.size(); ++i) 936 thread[i]->connectMemPorts(thread[i]->getTC()); 937} 938#endif 939 940template <class Impl> 941void 942FullO3CPU<Impl>::trap(Fault fault, unsigned tid) 943{ 944 // Pass the thread's TC into the invoke method. 945 fault->invoke(this->threadContexts[tid]); 946} 947 948#if !FULL_SYSTEM 949 950template <class Impl> 951void 952FullO3CPU<Impl>::syscall(int64_t callnum, int tid) 953{ 954 DPRINTF(O3CPU, "[tid:%i] Executing syscall().\n\n", tid); 955 956 DPRINTF(Activity,"Activity: syscall() called.\n"); 957 958 // Temporarily increase this by one to account for the syscall 959 // instruction. 960 ++(this->thread[tid]->funcExeInst); 961 962 // Execute the actual syscall. 963 this->thread[tid]->syscall(callnum); 964 965 // Decrease funcExeInst by one as the normal commit will handle 966 // incrementing it. 967 --(this->thread[tid]->funcExeInst); 968} 969 970template <class Impl> 971void 972FullO3CPU<Impl>::setSyscallReturn(SyscallReturn return_value, int tid) 973{ 974 TheISA::setSyscallReturn(return_value, this->tcBase(tid)); 975} 976 977#endif 978 979template <class Impl> 980void 981FullO3CPU<Impl>::serialize(std::ostream &os) 982{ 983 SimObject::State so_state = SimObject::getState(); 984 SERIALIZE_ENUM(so_state); 985 BaseCPU::serialize(os); 986 nameOut(os, csprintf("%s.tickEvent", name())); 987 tickEvent.serialize(os); 988 989 // Use SimpleThread's ability to checkpoint to make it easier to 990 // write out the registers. Also make this static so it doesn't 991 // get instantiated multiple times (causes a panic in statistics). 992 static SimpleThread temp; 993 994 for (int i = 0; i < thread.size(); i++) { 995 nameOut(os, csprintf("%s.xc.%i", name(), i)); 996 temp.copyTC(thread[i]->getTC()); 997 temp.serialize(os); 998 } 999} 1000 1001template <class Impl> 1002void 1003FullO3CPU<Impl>::unserialize(Checkpoint *cp, const std::string §ion) 1004{ 1005 SimObject::State so_state; 1006 UNSERIALIZE_ENUM(so_state); 1007 BaseCPU::unserialize(cp, section); 1008 tickEvent.unserialize(cp, csprintf("%s.tickEvent", section)); 1009 1010 // Use SimpleThread's ability to checkpoint to make it easier to 1011 // read in the registers. Also make this static so it doesn't 1012 // get instantiated multiple times (causes a panic in statistics). 1013 static SimpleThread temp; 1014 1015 for (int i = 0; i < thread.size(); i++) { 1016 temp.copyTC(thread[i]->getTC()); 1017 temp.unserialize(cp, csprintf("%s.xc.%i", section, i)); 1018 thread[i]->getTC()->copyArchRegs(temp.getTC()); 1019 } 1020} 1021 1022template <class Impl> 1023unsigned int 1024FullO3CPU<Impl>::drain(Event *drain_event) 1025{ 1026 DPRINTF(O3CPU, "Switching out\n"); 1027 1028 // If the CPU isn't doing anything, then return immediately. 1029 if (_status == Idle || _status == SwitchedOut) { 1030 return 0; 1031 } 1032 1033 drainCount = 0; 1034 fetch.drain(); 1035 decode.drain(); 1036 rename.drain(); 1037 iew.drain(); 1038 commit.drain(); 1039 1040 // Wake the CPU and record activity so everything can drain out if 1041 // the CPU was not able to immediately drain. 1042 if (getState() != SimObject::Drained) { 1043 // A bit of a hack...set the drainEvent after all the drain() 1044 // calls have been made, that way if all of the stages drain 1045 // immediately, the signalDrained() function knows not to call 1046 // process on the drain event. 1047 drainEvent = drain_event; 1048 1049 wakeCPU(); 1050 activityRec.activity(); 1051 1052 return 1; 1053 } else { 1054 return 0; 1055 } 1056} 1057 1058template <class Impl> 1059void 1060FullO3CPU<Impl>::resume() 1061{ 1062 fetch.resume(); 1063 decode.resume(); 1064 rename.resume(); 1065 iew.resume(); 1066 commit.resume(); 1067 1068 changeState(SimObject::Running); 1069 1070 if (_status == SwitchedOut || _status == Idle) 1071 return; 1072 1073#if FULL_SYSTEM 1074 assert(system->getMemoryMode() == Enums::timing); 1075#endif 1076 1077 if (!tickEvent.scheduled()) 1078 schedule(tickEvent, nextCycle()); 1079 _status = Running; 1080} 1081 1082template <class Impl> 1083void 1084FullO3CPU<Impl>::signalDrained() 1085{ 1086 if (++drainCount == NumStages) { 1087 if (tickEvent.scheduled()) 1088 tickEvent.squash(); 1089 1090 changeState(SimObject::Drained); 1091 1092 BaseCPU::switchOut(); 1093 1094 if (drainEvent) { 1095 drainEvent->process(); 1096 drainEvent = NULL; 1097 } 1098 } 1099 assert(drainCount <= 5); 1100} 1101 1102template <class Impl> 1103void 1104FullO3CPU<Impl>::switchOut() 1105{ 1106 fetch.switchOut(); 1107 rename.switchOut(); 1108 iew.switchOut(); 1109 commit.switchOut(); 1110 instList.clear(); 1111 while (!removeList.empty()) { 1112 removeList.pop(); 1113 } 1114 1115 _status = SwitchedOut; 1116#if USE_CHECKER 1117 if (checker) 1118 checker->switchOut(); 1119#endif 1120 if (tickEvent.scheduled()) 1121 tickEvent.squash(); 1122} 1123 1124template <class Impl> 1125void 1126FullO3CPU<Impl>::takeOverFrom(BaseCPU *oldCPU) 1127{ 1128 // Flush out any old data from the time buffers. 1129 for (int i = 0; i < timeBuffer.getSize(); ++i) { 1130 timeBuffer.advance(); 1131 fetchQueue.advance(); 1132 decodeQueue.advance(); 1133 renameQueue.advance(); 1134 iewQueue.advance(); 1135 } 1136 1137 activityRec.reset(); 1138 1139 BaseCPU::takeOverFrom(oldCPU, fetch.getIcachePort(), iew.getDcachePort()); 1140 1141 fetch.takeOverFrom(); 1142 decode.takeOverFrom(); 1143 rename.takeOverFrom(); 1144 iew.takeOverFrom(); 1145 commit.takeOverFrom(); 1146 1147 assert(!tickEvent.scheduled()); 1148 1149 // @todo: Figure out how to properly select the tid to put onto 1150 // the active threads list. 1151 int tid = 0; 1152 1153 std::list<unsigned>::iterator isActive = 1154 std::find(activeThreads.begin(), activeThreads.end(), tid); 1155 1156 if (isActive == activeThreads.end()) { 1157 //May Need to Re-code this if the delay variable is the delay 1158 //needed for thread to activate 1159 DPRINTF(O3CPU, "Adding Thread %i to active threads list\n", 1160 tid); 1161 1162 activeThreads.push_back(tid); 1163 } 1164 1165 // Set all statuses to active, schedule the CPU's tick event. 1166 // @todo: Fix up statuses so this is handled properly 1167 for (int i = 0; i < threadContexts.size(); ++i) { 1168 ThreadContext *tc = threadContexts[i]; 1169 if (tc->status() == ThreadContext::Active && _status != Running) { 1170 _status = Running; 1171 schedule(tickEvent, nextCycle()); 1172 } 1173 } 1174 if (!tickEvent.scheduled()) 1175 schedule(tickEvent, nextCycle()); 1176} 1177 1178template <class Impl> 1179TheISA::MiscReg 1180FullO3CPU<Impl>::readMiscRegNoEffect(int misc_reg, unsigned tid) 1181{ 1182 return this->regFile.readMiscRegNoEffect(misc_reg, tid); 1183} 1184 1185template <class Impl> 1186TheISA::MiscReg 1187FullO3CPU<Impl>::readMiscReg(int misc_reg, unsigned tid) 1188{ 1189 return this->regFile.readMiscReg(misc_reg, tid); 1190} 1191 1192template <class Impl> 1193void 1194FullO3CPU<Impl>::setMiscRegNoEffect(int misc_reg, 1195 const TheISA::MiscReg &val, unsigned tid) 1196{ 1197 this->regFile.setMiscRegNoEffect(misc_reg, val, tid); 1198} 1199 1200template <class Impl> 1201void 1202FullO3CPU<Impl>::setMiscReg(int misc_reg, 1203 const TheISA::MiscReg &val, unsigned tid) 1204{ 1205 this->regFile.setMiscReg(misc_reg, val, tid); 1206} 1207 1208template <class Impl> 1209uint64_t 1210FullO3CPU<Impl>::readIntReg(int reg_idx) 1211{ 1212 return regFile.readIntReg(reg_idx); 1213} 1214 1215template <class Impl> 1216FloatReg 1217FullO3CPU<Impl>::readFloatReg(int reg_idx, int width) 1218{ 1219 return regFile.readFloatReg(reg_idx, width); 1220} 1221 1222template <class Impl> 1223FloatReg 1224FullO3CPU<Impl>::readFloatReg(int reg_idx) 1225{ 1226 return regFile.readFloatReg(reg_idx); 1227} 1228 1229template <class Impl> 1230FloatRegBits 1231FullO3CPU<Impl>::readFloatRegBits(int reg_idx, int width) 1232{ 1233 return regFile.readFloatRegBits(reg_idx, width); 1234} 1235 1236template <class Impl> 1237FloatRegBits 1238FullO3CPU<Impl>::readFloatRegBits(int reg_idx) 1239{ 1240 return regFile.readFloatRegBits(reg_idx); 1241} 1242 1243template <class Impl> 1244void 1245FullO3CPU<Impl>::setIntReg(int reg_idx, uint64_t val) 1246{ 1247 regFile.setIntReg(reg_idx, val); 1248} 1249 1250template <class Impl> 1251void 1252FullO3CPU<Impl>::setFloatReg(int reg_idx, FloatReg val, int width) 1253{ 1254 regFile.setFloatReg(reg_idx, val, width); 1255} 1256 1257template <class Impl> 1258void 1259FullO3CPU<Impl>::setFloatReg(int reg_idx, FloatReg val) 1260{ 1261 regFile.setFloatReg(reg_idx, val); 1262} 1263 1264template <class Impl> 1265void 1266FullO3CPU<Impl>::setFloatRegBits(int reg_idx, FloatRegBits val, int width) 1267{ 1268 regFile.setFloatRegBits(reg_idx, val, width); 1269} 1270 1271template <class Impl> 1272void 1273FullO3CPU<Impl>::setFloatRegBits(int reg_idx, FloatRegBits val) 1274{ 1275 regFile.setFloatRegBits(reg_idx, val); 1276} 1277 1278template <class Impl> 1279uint64_t 1280FullO3CPU<Impl>::readArchIntReg(int reg_idx, unsigned tid) 1281{ 1282 PhysRegIndex phys_reg = commitRenameMap[tid].lookup(reg_idx); 1283 1284 return regFile.readIntReg(phys_reg); 1285} 1286 1287template <class Impl> 1288float 1289FullO3CPU<Impl>::readArchFloatRegSingle(int reg_idx, unsigned tid) 1290{ 1291 int idx = reg_idx + TheISA::FP_Base_DepTag; 1292 PhysRegIndex phys_reg = commitRenameMap[tid].lookup(idx); 1293 1294 return regFile.readFloatReg(phys_reg); 1295} 1296 1297template <class Impl> 1298double 1299FullO3CPU<Impl>::readArchFloatRegDouble(int reg_idx, unsigned tid) 1300{ 1301 int idx = reg_idx + TheISA::FP_Base_DepTag; 1302 PhysRegIndex phys_reg = commitRenameMap[tid].lookup(idx); 1303 1304 return regFile.readFloatReg(phys_reg, 64); 1305} 1306 1307template <class Impl> 1308uint64_t 1309FullO3CPU<Impl>::readArchFloatRegInt(int reg_idx, unsigned tid) 1310{ 1311 int idx = reg_idx + TheISA::FP_Base_DepTag; 1312 PhysRegIndex phys_reg = commitRenameMap[tid].lookup(idx); 1313 1314 return regFile.readFloatRegBits(phys_reg); 1315} 1316 1317template <class Impl> 1318void 1319FullO3CPU<Impl>::setArchIntReg(int reg_idx, uint64_t val, unsigned tid) 1320{ 1321 PhysRegIndex phys_reg = commitRenameMap[tid].lookup(reg_idx); 1322 1323 regFile.setIntReg(phys_reg, val); 1324} 1325 1326template <class Impl> 1327void 1328FullO3CPU<Impl>::setArchFloatRegSingle(int reg_idx, float val, unsigned tid) 1329{ 1330 int idx = reg_idx + TheISA::FP_Base_DepTag; 1331 PhysRegIndex phys_reg = commitRenameMap[tid].lookup(idx); 1332 1333 regFile.setFloatReg(phys_reg, val); 1334} 1335 1336template <class Impl> 1337void 1338FullO3CPU<Impl>::setArchFloatRegDouble(int reg_idx, double val, unsigned tid) 1339{ 1340 int idx = reg_idx + TheISA::FP_Base_DepTag; 1341 PhysRegIndex phys_reg = commitRenameMap[tid].lookup(idx); 1342 1343 regFile.setFloatReg(phys_reg, val, 64); 1344} 1345 1346template <class Impl> 1347void 1348FullO3CPU<Impl>::setArchFloatRegInt(int reg_idx, uint64_t val, unsigned tid) 1349{ 1350 int idx = reg_idx + TheISA::FP_Base_DepTag; 1351 PhysRegIndex phys_reg = commitRenameMap[tid].lookup(idx); 1352 1353 regFile.setFloatRegBits(phys_reg, val); 1354} 1355 1356template <class Impl> 1357uint64_t 1358FullO3CPU<Impl>::readPC(unsigned tid) 1359{ 1360 return commit.readPC(tid); 1361} 1362 1363template <class Impl> 1364void 1365FullO3CPU<Impl>::setPC(Addr new_PC,unsigned tid) 1366{ 1367 commit.setPC(new_PC, tid); 1368} 1369 1370template <class Impl> 1371uint64_t 1372FullO3CPU<Impl>::readMicroPC(unsigned tid) 1373{ 1374 return commit.readMicroPC(tid); 1375} 1376 1377template <class Impl> 1378void 1379FullO3CPU<Impl>::setMicroPC(Addr new_PC,unsigned tid) 1380{ 1381 commit.setMicroPC(new_PC, tid); 1382} 1383 1384template <class Impl> 1385uint64_t 1386FullO3CPU<Impl>::readNextPC(unsigned tid) 1387{ 1388 return commit.readNextPC(tid); 1389} 1390 1391template <class Impl> 1392void 1393FullO3CPU<Impl>::setNextPC(uint64_t val,unsigned tid) 1394{ 1395 commit.setNextPC(val, tid); 1396} 1397 1398template <class Impl> 1399uint64_t 1400FullO3CPU<Impl>::readNextNPC(unsigned tid) 1401{ 1402 return commit.readNextNPC(tid); 1403} 1404 1405template <class Impl> 1406void 1407FullO3CPU<Impl>::setNextNPC(uint64_t val,unsigned tid) 1408{ 1409 commit.setNextNPC(val, tid); 1410} 1411 1412template <class Impl> 1413uint64_t 1414FullO3CPU<Impl>::readNextMicroPC(unsigned tid) 1415{ 1416 return commit.readNextMicroPC(tid); 1417} 1418 1419template <class Impl> 1420void 1421FullO3CPU<Impl>::setNextMicroPC(Addr new_PC,unsigned tid) 1422{ 1423 commit.setNextMicroPC(new_PC, tid); 1424} 1425 1426template <class Impl> 1427void 1428FullO3CPU<Impl>::squashFromTC(unsigned tid) 1429{ 1430 this->thread[tid]->inSyscall = true; 1431 this->commit.generateTCEvent(tid); 1432} 1433 1434template <class Impl> 1435typename FullO3CPU<Impl>::ListIt 1436FullO3CPU<Impl>::addInst(DynInstPtr &inst) 1437{ 1438 instList.push_back(inst); 1439 1440 return --(instList.end()); 1441} 1442 1443template <class Impl> 1444void 1445FullO3CPU<Impl>::instDone(unsigned tid) 1446{ 1447 // Keep an instruction count. 1448 thread[tid]->numInst++; 1449 thread[tid]->numInsts++; 1450 committedInsts[tid]++; 1451 totalCommittedInsts++; 1452 1453 // Check for instruction-count-based events. 1454 comInstEventQueue[tid]->serviceEvents(thread[tid]->numInst); 1455} 1456 1457template <class Impl> 1458void 1459FullO3CPU<Impl>::addToRemoveList(DynInstPtr &inst) 1460{ 1461 removeInstsThisCycle = true; 1462 1463 removeList.push(inst->getInstListIt()); 1464} 1465 1466template <class Impl> 1467void 1468FullO3CPU<Impl>::removeFrontInst(DynInstPtr &inst) 1469{ 1470 DPRINTF(O3CPU, "Removing committed instruction [tid:%i] PC %#x " 1471 "[sn:%lli]\n", 1472 inst->threadNumber, inst->readPC(), inst->seqNum); 1473 1474 removeInstsThisCycle = true; 1475 1476 // Remove the front instruction. 1477 removeList.push(inst->getInstListIt()); 1478} 1479 1480template <class Impl> 1481void 1482FullO3CPU<Impl>::removeInstsNotInROB(unsigned tid) 1483{ 1484 DPRINTF(O3CPU, "Thread %i: Deleting instructions from instruction" 1485 " list.\n", tid); 1486 1487 ListIt end_it; 1488 1489 bool rob_empty = false; 1490 1491 if (instList.empty()) { 1492 return; 1493 } else if (rob.isEmpty(/*tid*/)) { 1494 DPRINTF(O3CPU, "ROB is empty, squashing all insts.\n"); 1495 end_it = instList.begin(); 1496 rob_empty = true; 1497 } else { 1498 end_it = (rob.readTailInst(tid))->getInstListIt(); 1499 DPRINTF(O3CPU, "ROB is not empty, squashing insts not in ROB.\n"); 1500 } 1501 1502 removeInstsThisCycle = true; 1503 1504 ListIt inst_it = instList.end(); 1505 1506 inst_it--; 1507 1508 // Walk through the instruction list, removing any instructions 1509 // that were inserted after the given instruction iterator, end_it. 1510 while (inst_it != end_it) { 1511 assert(!instList.empty()); 1512 1513 squashInstIt(inst_it, tid); 1514 1515 inst_it--; 1516 } 1517 1518 // If the ROB was empty, then we actually need to remove the first 1519 // instruction as well. 1520 if (rob_empty) { 1521 squashInstIt(inst_it, tid); 1522 } 1523} 1524 1525template <class Impl> 1526void 1527FullO3CPU<Impl>::removeInstsUntil(const InstSeqNum &seq_num, 1528 unsigned tid) 1529{ 1530 assert(!instList.empty()); 1531 1532 removeInstsThisCycle = true; 1533 1534 ListIt inst_iter = instList.end(); 1535 1536 inst_iter--; 1537 1538 DPRINTF(O3CPU, "Deleting instructions from instruction " 1539 "list that are from [tid:%i] and above [sn:%lli] (end=%lli).\n", 1540 tid, seq_num, (*inst_iter)->seqNum); 1541 1542 while ((*inst_iter)->seqNum > seq_num) { 1543 1544 bool break_loop = (inst_iter == instList.begin()); 1545 1546 squashInstIt(inst_iter, tid); 1547 1548 inst_iter--; 1549 1550 if (break_loop) 1551 break; 1552 } 1553} 1554 1555template <class Impl> 1556inline void 1557FullO3CPU<Impl>::squashInstIt(const ListIt &instIt, const unsigned &tid) 1558{ 1559 if ((*instIt)->threadNumber == tid) { 1560 DPRINTF(O3CPU, "Squashing instruction, " 1561 "[tid:%i] [sn:%lli] PC %#x\n", 1562 (*instIt)->threadNumber, 1563 (*instIt)->seqNum, 1564 (*instIt)->readPC()); 1565 1566 // Mark it as squashed. 1567 (*instIt)->setSquashed(); 1568 1569 // @todo: Formulate a consistent method for deleting 1570 // instructions from the instruction list 1571 // Remove the instruction from the list. 1572 removeList.push(instIt); 1573 } 1574} 1575 1576template <class Impl> 1577void 1578FullO3CPU<Impl>::cleanUpRemovedInsts() 1579{ 1580 while (!removeList.empty()) { 1581 DPRINTF(O3CPU, "Removing instruction, " 1582 "[tid:%i] [sn:%lli] PC %#x\n", 1583 (*removeList.front())->threadNumber, 1584 (*removeList.front())->seqNum, 1585 (*removeList.front())->readPC()); 1586 1587 instList.erase(removeList.front()); 1588 1589 removeList.pop(); 1590 } 1591 1592 removeInstsThisCycle = false; 1593} 1594/* 1595template <class Impl> 1596void 1597FullO3CPU<Impl>::removeAllInsts() 1598{ 1599 instList.clear(); 1600} 1601*/ 1602template <class Impl> 1603void 1604FullO3CPU<Impl>::dumpInsts() 1605{ 1606 int num = 0; 1607 1608 ListIt inst_list_it = instList.begin(); 1609 1610 cprintf("Dumping Instruction List\n"); 1611 1612 while (inst_list_it != instList.end()) { 1613 cprintf("Instruction:%i\nPC:%#x\n[tid:%i]\n[sn:%lli]\nIssued:%i\n" 1614 "Squashed:%i\n\n", 1615 num, (*inst_list_it)->readPC(), (*inst_list_it)->threadNumber, 1616 (*inst_list_it)->seqNum, (*inst_list_it)->isIssued(), 1617 (*inst_list_it)->isSquashed()); 1618 inst_list_it++; 1619 ++num; 1620 } 1621} 1622/* 1623template <class Impl> 1624void 1625FullO3CPU<Impl>::wakeDependents(DynInstPtr &inst) 1626{ 1627 iew.wakeDependents(inst); 1628} 1629*/ 1630template <class Impl> 1631void 1632FullO3CPU<Impl>::wakeCPU() 1633{ 1634 if (activityRec.active() || tickEvent.scheduled()) { 1635 DPRINTF(Activity, "CPU already running.\n"); 1636 return; 1637 } 1638 1639 DPRINTF(Activity, "Waking up CPU\n"); 1640 1641 idleCycles += tickToCycles((curTick - 1) - lastRunningCycle); 1642 numCycles += tickToCycles((curTick - 1) - lastRunningCycle); 1643 1644 schedule(tickEvent, nextCycle()); 1645} 1646 1647template <class Impl> 1648int 1649FullO3CPU<Impl>::getFreeTid() 1650{ 1651 for (int i=0; i < numThreads; i++) { 1652 if (!tids[i]) { 1653 tids[i] = true; 1654 return i; 1655 } 1656 } 1657 1658 return -1; 1659} 1660 1661template <class Impl> 1662void 1663FullO3CPU<Impl>::doContextSwitch() 1664{ 1665 if (contextSwitch) { 1666 1667 //ADD CODE TO DEACTIVE THREAD HERE (???) 1668 1669 for (int tid=0; tid < cpuWaitList.size(); tid++) { 1670 activateWhenReady(tid); 1671 } 1672 1673 if (cpuWaitList.size() == 0) 1674 contextSwitch = true; 1675 } 1676} 1677 1678template <class Impl> 1679void 1680FullO3CPU<Impl>::updateThreadPriority() 1681{ 1682 if (activeThreads.size() > 1) 1683 { 1684 //DEFAULT TO ROUND ROBIN SCHEME 1685 //e.g. Move highest priority to end of thread list 1686 std::list<unsigned>::iterator list_begin = activeThreads.begin(); 1687 std::list<unsigned>::iterator list_end = activeThreads.end(); 1688 1689 unsigned high_thread = *list_begin; 1690 1691 activeThreads.erase(list_begin); 1692 1693 activeThreads.push_back(high_thread); 1694 } 1695} 1696 1697// Forward declaration of FullO3CPU. 1698template class FullO3CPU<O3CPUImpl>; 1699