74#endif 75 76struct BaseCPUParams; 77 78using namespace TheISA; 79using namespace std; 80 81BaseO3CPU::BaseO3CPU(BaseCPUParams *params) 82 : BaseCPU(params) 83{ 84} 85 86void 87BaseO3CPU::regStats() 88{ 89 BaseCPU::regStats(); 90} 91 92template<class Impl> 93bool 94FullO3CPU<Impl>::IcachePort::recvTimingResp(PacketPtr pkt) 95{ 96 DPRINTF(O3CPU, "Fetch unit received timing\n"); 97 // We shouldn't ever get a cacheable block in Modified state 98 assert(pkt->req->isUncacheable() || 99 !(pkt->cacheResponding() && !pkt->hasSharers())); 100 fetch->processCacheCompletion(pkt); 101 102 return true; 103} 104 105template<class Impl> 106void 107FullO3CPU<Impl>::IcachePort::recvReqRetry() 108{ 109 fetch->recvReqRetry(); 110} 111 112template <class Impl> 113bool 114FullO3CPU<Impl>::DcachePort::recvTimingResp(PacketPtr pkt) 115{ 116 return lsq->recvTimingResp(pkt); 117} 118 119template <class Impl> 120void 121FullO3CPU<Impl>::DcachePort::recvTimingSnoopReq(PacketPtr pkt) 122{ 123 for (ThreadID tid = 0; tid < cpu->numThreads; tid++) { 124 if (cpu->getCpuAddrMonitor(tid)->doMonitor(pkt)) { 125 cpu->wakeup(tid); 126 } 127 } 128 lsq->recvTimingSnoopReq(pkt); 129} 130 131template <class Impl> 132void 133FullO3CPU<Impl>::DcachePort::recvReqRetry() 134{ 135 lsq->recvReqRetry(); 136} 137 138template <class Impl> 139FullO3CPU<Impl>::TickEvent::TickEvent(FullO3CPU<Impl> *c) 140 : Event(CPU_Tick_Pri), cpu(c) 141{ 142} 143 144template <class Impl> 145void 146FullO3CPU<Impl>::TickEvent::process() 147{ 148 cpu->tick(); 149} 150 151template <class Impl> 152const char * 153FullO3CPU<Impl>::TickEvent::description() const 154{ 155 return "FullO3CPU tick"; 156} 157 158template <class Impl> 159FullO3CPU<Impl>::FullO3CPU(DerivO3CPUParams *params) 160 : BaseO3CPU(params), 161 itb(params->itb), 162 dtb(params->dtb), 163 tickEvent(this), 164#ifndef NDEBUG 165 instcount(0), 166#endif 167 removeInstsThisCycle(false), 168 fetch(this, params), 169 decode(this, params), 170 rename(this, params), 171 iew(this, params), 172 commit(this, params), 173 174 regFile(params->numPhysIntRegs, 175 params->numPhysFloatRegs, 176 params->numPhysCCRegs), 177 178 freeList(name() + ".freelist", ®File), 179 180 rob(this, params), 181 182 scoreboard(name() + ".scoreboard", 183 regFile.totalNumPhysRegs(), TheISA::NumMiscRegs, 184 TheISA::ZeroReg, TheISA::ZeroReg), 185 186 isa(numThreads, NULL), 187 188 icachePort(&fetch, this), 189 dcachePort(&iew.ldstQueue, this), 190 191 timeBuffer(params->backComSize, params->forwardComSize), 192 fetchQueue(params->backComSize, params->forwardComSize), 193 decodeQueue(params->backComSize, params->forwardComSize), 194 renameQueue(params->backComSize, params->forwardComSize), 195 iewQueue(params->backComSize, params->forwardComSize), 196 activityRec(name(), NumStages, 197 params->backComSize + params->forwardComSize, 198 params->activity), 199 200 globalSeqNum(1), 201 system(params->system), 202 lastRunningCycle(curCycle()) 203{ 204 if (!params->switched_out) { 205 _status = Running; 206 } else { 207 _status = SwitchedOut; 208 } 209 210 if (params->checker) { 211 BaseCPU *temp_checker = params->checker; 212 checker = dynamic_cast<Checker<Impl> *>(temp_checker); 213 checker->setIcachePort(&icachePort); 214 checker->setSystem(params->system); 215 } else { 216 checker = NULL; 217 } 218 219 if (!FullSystem) { 220 thread.resize(numThreads); 221 tids.resize(numThreads); 222 } 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 ThreadID active_threads; 259 if (FullSystem) { 260 active_threads = 1; 261 } else { 262 active_threads = params->workload.size(); 263 264 if (active_threads > Impl::MaxThreads) { 265 panic("Workload Size too large. Increase the 'MaxThreads' " 266 "constant in your O3CPU impl. file (e.g. o3/alpha/impl.hh) " 267 "or edit your workload size."); 268 } 269 } 270 271 //Make Sure That this a Valid Architeture 272 assert(params->numPhysIntRegs >= numThreads * TheISA::NumIntRegs); 273 assert(params->numPhysFloatRegs >= numThreads * TheISA::NumFloatRegs); 274 assert(params->numPhysCCRegs >= numThreads * TheISA::NumCCRegs); 275 276 rename.setScoreboard(&scoreboard); 277 iew.setScoreboard(&scoreboard); 278 279 // Setup the rename map for whichever stages need it. 280 for (ThreadID tid = 0; tid < numThreads; tid++) { 281 isa[tid] = params->isa[tid]; 282 283 // Only Alpha has an FP zero register, so for other ISAs we 284 // use an invalid FP register index to avoid special treatment 285 // of any valid FP reg. 286 RegIndex invalidFPReg = TheISA::NumFloatRegs + 1; 287 RegIndex fpZeroReg = 288 (THE_ISA == ALPHA_ISA) ? TheISA::ZeroReg : invalidFPReg; 289 290 commitRenameMap[tid].init(®File, TheISA::ZeroReg, fpZeroReg, 291 &freeList); 292 293 renameMap[tid].init(®File, TheISA::ZeroReg, fpZeroReg, 294 &freeList); 295 } 296 297 // Initialize rename map to assign physical registers to the 298 // architectural registers for active threads only. 299 for (ThreadID tid = 0; tid < active_threads; tid++) { 300 for (RegIndex ridx = 0; ridx < TheISA::NumIntRegs; ++ridx) { 301 // Note that we can't use the rename() method because we don't 302 // want special treatment for the zero register at this point 303 PhysRegIndex phys_reg = freeList.getIntReg(); 304 renameMap[tid].setIntEntry(ridx, phys_reg); 305 commitRenameMap[tid].setIntEntry(ridx, phys_reg); 306 } 307 308 for (RegIndex ridx = 0; ridx < TheISA::NumFloatRegs; ++ridx) { 309 PhysRegIndex phys_reg = freeList.getFloatReg(); 310 renameMap[tid].setFloatEntry(ridx, phys_reg); 311 commitRenameMap[tid].setFloatEntry(ridx, phys_reg); 312 } 313 314 for (RegIndex ridx = 0; ridx < TheISA::NumCCRegs; ++ridx) { 315 PhysRegIndex phys_reg = freeList.getCCReg(); 316 renameMap[tid].setCCEntry(ridx, phys_reg); 317 commitRenameMap[tid].setCCEntry(ridx, phys_reg); 318 } 319 } 320 321 rename.setRenameMap(renameMap); 322 commit.setRenameMap(commitRenameMap); 323 rename.setFreeList(&freeList); 324 325 // Setup the ROB for whichever stages need it. 326 commit.setROB(&rob); 327 328 lastActivatedCycle = 0; 329#if 0 330 // Give renameMap & rename stage access to the freeList; 331 for (ThreadID tid = 0; tid < numThreads; tid++) 332 globalSeqNum[tid] = 1; 333#endif 334 335 DPRINTF(O3CPU, "Creating O3CPU object.\n"); 336 337 // Setup any thread state. 338 this->thread.resize(this->numThreads); 339 340 for (ThreadID tid = 0; tid < this->numThreads; ++tid) { 341 if (FullSystem) { 342 // SMT is not supported in FS mode yet. 343 assert(this->numThreads == 1); 344 this->thread[tid] = new Thread(this, 0, NULL); 345 } else { 346 if (tid < params->workload.size()) { 347 DPRINTF(O3CPU, "Workload[%i] process is %#x", 348 tid, this->thread[tid]); 349 this->thread[tid] = new typename FullO3CPU<Impl>::Thread( 350 (typename Impl::O3CPU *)(this), 351 tid, params->workload[tid]); 352 353 //usedTids[tid] = true; 354 //threadMap[tid] = tid; 355 } else { 356 //Allocate Empty thread so M5 can use later 357 //when scheduling threads to CPU 358 Process* dummy_proc = NULL; 359 360 this->thread[tid] = new typename FullO3CPU<Impl>::Thread( 361 (typename Impl::O3CPU *)(this), 362 tid, dummy_proc); 363 //usedTids[tid] = false; 364 } 365 } 366 367 ThreadContext *tc; 368 369 // Setup the TC that will serve as the interface to the threads/CPU. 370 O3ThreadContext<Impl> *o3_tc = new O3ThreadContext<Impl>; 371 372 tc = o3_tc; 373 374 // If we're using a checker, then the TC should be the 375 // CheckerThreadContext. 376 if (params->checker) { 377 tc = new CheckerThreadContext<O3ThreadContext<Impl> >( 378 o3_tc, this->checker); 379 } 380 381 o3_tc->cpu = (typename Impl::O3CPU *)(this); 382 assert(o3_tc->cpu); 383 o3_tc->thread = this->thread[tid]; 384 385 // Setup quiesce event. 386 this->thread[tid]->quiesceEvent = new EndQuiesceEvent(tc); 387 388 // Give the thread the TC. 389 this->thread[tid]->tc = tc; 390 391 // Add the TC to the CPU's list of TC's. 392 this->threadContexts.push_back(tc); 393 } 394 395 // FullO3CPU always requires an interrupt controller. 396 if (!params->switched_out && interrupts.empty()) { 397 fatal("FullO3CPU %s has no interrupt controller.\n" 398 "Ensure createInterruptController() is called.\n", name()); 399 } 400 401 for (ThreadID tid = 0; tid < this->numThreads; tid++) 402 this->thread[tid]->setFuncExeInst(0); 403} 404 405template <class Impl> 406FullO3CPU<Impl>::~FullO3CPU() 407{ 408} 409 410template <class Impl> 411void 412FullO3CPU<Impl>::regProbePoints() 413{ 414 BaseCPU::regProbePoints(); 415 416 ppInstAccessComplete = new ProbePointArg<PacketPtr>(getProbeManager(), "InstAccessComplete"); 417 ppDataAccessComplete = new ProbePointArg<std::pair<DynInstPtr, PacketPtr> >(getProbeManager(), "DataAccessComplete"); 418 419 fetch.regProbePoints(); 420 rename.regProbePoints(); 421 iew.regProbePoints(); 422 commit.regProbePoints(); 423} 424 425template <class Impl> 426void 427FullO3CPU<Impl>::regStats() 428{ 429 BaseO3CPU::regStats(); 430 431 // Register any of the O3CPU's stats here. 432 timesIdled 433 .name(name() + ".timesIdled") 434 .desc("Number of times that the entire CPU went into an idle state and" 435 " unscheduled itself") 436 .prereq(timesIdled); 437 438 idleCycles 439 .name(name() + ".idleCycles") 440 .desc("Total number of cycles that the CPU has spent unscheduled due " 441 "to idling") 442 .prereq(idleCycles); 443 444 quiesceCycles 445 .name(name() + ".quiesceCycles") 446 .desc("Total number of cycles that CPU has spent quiesced or waiting " 447 "for an interrupt") 448 .prereq(quiesceCycles); 449 450 // Number of Instructions simulated 451 // -------------------------------- 452 // Should probably be in Base CPU but need templated 453 // MaxThreads so put in here instead 454 committedInsts 455 .init(numThreads) 456 .name(name() + ".committedInsts") 457 .desc("Number of Instructions Simulated") 458 .flags(Stats::total); 459 460 committedOps 461 .init(numThreads) 462 .name(name() + ".committedOps") 463 .desc("Number of Ops (including micro ops) Simulated") 464 .flags(Stats::total); 465 466 cpi 467 .name(name() + ".cpi") 468 .desc("CPI: Cycles Per Instruction") 469 .precision(6); 470 cpi = numCycles / committedInsts; 471 472 totalCpi 473 .name(name() + ".cpi_total") 474 .desc("CPI: Total CPI of All Threads") 475 .precision(6); 476 totalCpi = numCycles / sum(committedInsts); 477 478 ipc 479 .name(name() + ".ipc") 480 .desc("IPC: Instructions Per Cycle") 481 .precision(6); 482 ipc = committedInsts / numCycles; 483 484 totalIpc 485 .name(name() + ".ipc_total") 486 .desc("IPC: Total IPC of All Threads") 487 .precision(6); 488 totalIpc = sum(committedInsts) / numCycles; 489 490 this->fetch.regStats(); 491 this->decode.regStats(); 492 this->rename.regStats(); 493 this->iew.regStats(); 494 this->commit.regStats(); 495 this->rob.regStats(); 496 497 intRegfileReads 498 .name(name() + ".int_regfile_reads") 499 .desc("number of integer regfile reads") 500 .prereq(intRegfileReads); 501 502 intRegfileWrites 503 .name(name() + ".int_regfile_writes") 504 .desc("number of integer regfile writes") 505 .prereq(intRegfileWrites); 506 507 fpRegfileReads 508 .name(name() + ".fp_regfile_reads") 509 .desc("number of floating regfile reads") 510 .prereq(fpRegfileReads); 511 512 fpRegfileWrites 513 .name(name() + ".fp_regfile_writes") 514 .desc("number of floating regfile writes") 515 .prereq(fpRegfileWrites); 516 517 ccRegfileReads 518 .name(name() + ".cc_regfile_reads") 519 .desc("number of cc regfile reads") 520 .prereq(ccRegfileReads); 521 522 ccRegfileWrites 523 .name(name() + ".cc_regfile_writes") 524 .desc("number of cc regfile writes") 525 .prereq(ccRegfileWrites); 526 527 miscRegfileReads 528 .name(name() + ".misc_regfile_reads") 529 .desc("number of misc regfile reads") 530 .prereq(miscRegfileReads); 531 532 miscRegfileWrites 533 .name(name() + ".misc_regfile_writes") 534 .desc("number of misc regfile writes") 535 .prereq(miscRegfileWrites); 536} 537 538template <class Impl> 539void 540FullO3CPU<Impl>::tick() 541{ 542 DPRINTF(O3CPU, "\n\nFullO3CPU: Ticking main, FullO3CPU.\n"); 543 assert(!switchedOut()); 544 assert(drainState() != DrainState::Drained); 545 546 ++numCycles; 547 ppCycles->notify(1); 548 549// activity = false; 550 551 //Tick each of the stages 552 fetch.tick(); 553 554 decode.tick(); 555 556 rename.tick(); 557 558 iew.tick(); 559 560 commit.tick(); 561 562 // Now advance the time buffers 563 timeBuffer.advance(); 564 565 fetchQueue.advance(); 566 decodeQueue.advance(); 567 renameQueue.advance(); 568 iewQueue.advance(); 569 570 activityRec.advance(); 571 572 if (removeInstsThisCycle) { 573 cleanUpRemovedInsts(); 574 } 575 576 if (!tickEvent.scheduled()) { 577 if (_status == SwitchedOut) { 578 DPRINTF(O3CPU, "Switched out!\n"); 579 // increment stat 580 lastRunningCycle = curCycle(); 581 } else if (!activityRec.active() || _status == Idle) { 582 DPRINTF(O3CPU, "Idle!\n"); 583 lastRunningCycle = curCycle(); 584 timesIdled++; 585 } else { 586 schedule(tickEvent, clockEdge(Cycles(1))); 587 DPRINTF(O3CPU, "Scheduling next tick!\n"); 588 } 589 } 590 591 if (!FullSystem) 592 updateThreadPriority(); 593 594 tryDrain(); 595} 596 597template <class Impl> 598void 599FullO3CPU<Impl>::init() 600{ 601 BaseCPU::init(); 602 603 for (ThreadID tid = 0; tid < numThreads; ++tid) { 604 // Set noSquashFromTC so that the CPU doesn't squash when initially 605 // setting up registers. 606 thread[tid]->noSquashFromTC = true; 607 // Initialise the ThreadContext's memory proxies 608 thread[tid]->initMemProxies(thread[tid]->getTC()); 609 } 610 611 if (FullSystem && !params()->switched_out) { 612 for (ThreadID tid = 0; tid < numThreads; tid++) { 613 ThreadContext *src_tc = threadContexts[tid]; 614 TheISA::initCPU(src_tc, src_tc->contextId()); 615 } 616 } 617 618 // Clear noSquashFromTC. 619 for (int tid = 0; tid < numThreads; ++tid) 620 thread[tid]->noSquashFromTC = false; 621 622 commit.setThreads(thread); 623} 624 625template <class Impl> 626void 627FullO3CPU<Impl>::startup() 628{ 629 BaseCPU::startup(); 630 for (int tid = 0; tid < numThreads; ++tid) 631 isa[tid]->startup(threadContexts[tid]); 632 633 fetch.startupStage(); 634 decode.startupStage(); 635 iew.startupStage(); 636 rename.startupStage(); 637 commit.startupStage(); 638} 639 640template <class Impl> 641void 642FullO3CPU<Impl>::activateThread(ThreadID tid) 643{ 644 list<ThreadID>::iterator isActive = 645 std::find(activeThreads.begin(), activeThreads.end(), tid); 646 647 DPRINTF(O3CPU, "[tid:%i]: Calling activate thread.\n", tid); 648 assert(!switchedOut()); 649 650 if (isActive == activeThreads.end()) { 651 DPRINTF(O3CPU, "[tid:%i]: Adding to active threads list\n", 652 tid); 653 654 activeThreads.push_back(tid); 655 } 656} 657 658template <class Impl> 659void 660FullO3CPU<Impl>::deactivateThread(ThreadID tid) 661{ 662 //Remove From Active List, if Active 663 list<ThreadID>::iterator thread_it = 664 std::find(activeThreads.begin(), activeThreads.end(), tid); 665 666 DPRINTF(O3CPU, "[tid:%i]: Calling deactivate thread.\n", tid); 667 assert(!switchedOut()); 668 669 if (thread_it != activeThreads.end()) { 670 DPRINTF(O3CPU,"[tid:%i]: Removing from active threads list\n", 671 tid); 672 activeThreads.erase(thread_it); 673 } 674 675 fetch.deactivateThread(tid); 676 commit.deactivateThread(tid); 677} 678 679template <class Impl> 680Counter 681FullO3CPU<Impl>::totalInsts() const 682{ 683 Counter total(0); 684 685 ThreadID size = thread.size(); 686 for (ThreadID i = 0; i < size; i++) 687 total += thread[i]->numInst; 688 689 return total; 690} 691 692template <class Impl> 693Counter 694FullO3CPU<Impl>::totalOps() const 695{ 696 Counter total(0); 697 698 ThreadID size = thread.size(); 699 for (ThreadID i = 0; i < size; i++) 700 total += thread[i]->numOp; 701 702 return total; 703} 704 705template <class Impl> 706void 707FullO3CPU<Impl>::activateContext(ThreadID tid) 708{ 709 assert(!switchedOut()); 710 711 // Needs to set each stage to running as well. 712 activateThread(tid); 713 714 // We don't want to wake the CPU if it is drained. In that case, 715 // we just want to flag the thread as active and schedule the tick 716 // event from drainResume() instead. 717 if (drainState() == DrainState::Drained) 718 return; 719 720 // If we are time 0 or if the last activation time is in the past, 721 // schedule the next tick and wake up the fetch unit 722 if (lastActivatedCycle == 0 || lastActivatedCycle < curTick()) { 723 scheduleTickEvent(Cycles(0)); 724 725 // Be sure to signal that there's some activity so the CPU doesn't 726 // deschedule itself. 727 activityRec.activity(); 728 fetch.wakeFromQuiesce(); 729 730 Cycles cycles(curCycle() - lastRunningCycle); 731 // @todo: This is an oddity that is only here to match the stats 732 if (cycles != 0) 733 --cycles; 734 quiesceCycles += cycles; 735 736 lastActivatedCycle = curTick(); 737 738 _status = Running; 739 740 BaseCPU::activateContext(tid); 741 } 742} 743 744template <class Impl> 745void 746FullO3CPU<Impl>::suspendContext(ThreadID tid) 747{ 748 DPRINTF(O3CPU,"[tid: %i]: Suspending Thread Context.\n", tid); 749 assert(!switchedOut()); 750 751 deactivateThread(tid); 752 753 // If this was the last thread then unschedule the tick event. 754 if (activeThreads.size() == 0) { 755 unscheduleTickEvent(); 756 lastRunningCycle = curCycle(); 757 _status = Idle; 758 } 759 760 DPRINTF(Quiesce, "Suspending Context\n"); 761 762 BaseCPU::suspendContext(tid); 763} 764 765template <class Impl> 766void 767FullO3CPU<Impl>::haltContext(ThreadID tid) 768{ 769 //For now, this is the same as deallocate 770 DPRINTF(O3CPU,"[tid:%i]: Halt Context called. Deallocating", tid); 771 assert(!switchedOut()); 772 773 deactivateThread(tid); 774 removeThread(tid); 775} 776 777template <class Impl> 778void 779FullO3CPU<Impl>::insertThread(ThreadID tid) 780{ 781 DPRINTF(O3CPU,"[tid:%i] Initializing thread into CPU"); 782 // Will change now that the PC and thread state is internal to the CPU 783 // and not in the ThreadContext. 784 ThreadContext *src_tc; 785 if (FullSystem) 786 src_tc = system->threadContexts[tid]; 787 else 788 src_tc = tcBase(tid); 789 790 //Bind Int Regs to Rename Map 791 for (int ireg = 0; ireg < TheISA::NumIntRegs; ireg++) { 792 PhysRegIndex phys_reg = freeList.getIntReg(); 793 794 renameMap[tid].setEntry(ireg,phys_reg); 795 scoreboard.setReg(phys_reg); 796 } 797 798 //Bind Float Regs to Rename Map 799 int max_reg = TheISA::FP_Reg_Base + TheISA::NumFloatRegs; 800 for (int freg = TheISA::FP_Reg_Base; freg < max_reg; freg++) { 801 PhysRegIndex phys_reg = freeList.getFloatReg(); 802 803 renameMap[tid].setEntry(freg,phys_reg); 804 scoreboard.setReg(phys_reg); 805 } 806 807 //Bind condition-code Regs to Rename Map 808 max_reg = TheISA::CC_Reg_Base + TheISA::NumCCRegs; 809 for (int creg = TheISA::CC_Reg_Base; 810 creg < max_reg; creg++) { 811 PhysRegIndex phys_reg = freeList.getCCReg(); 812 813 renameMap[tid].setEntry(creg,phys_reg); 814 scoreboard.setReg(phys_reg); 815 } 816 817 //Copy Thread Data Into RegFile 818 //this->copyFromTC(tid); 819 820 //Set PC/NPC/NNPC 821 pcState(src_tc->pcState(), tid); 822 823 src_tc->setStatus(ThreadContext::Active); 824 825 activateContext(tid); 826 827 //Reset ROB/IQ/LSQ Entries 828 commit.rob->resetEntries(); 829 iew.resetEntries(); 830} 831 832template <class Impl> 833void 834FullO3CPU<Impl>::removeThread(ThreadID tid) 835{ 836 DPRINTF(O3CPU,"[tid:%i] Removing thread context from CPU.\n", tid); 837 838 // Copy Thread Data From RegFile 839 // If thread is suspended, it might be re-allocated 840 // this->copyToTC(tid); 841 842 843 // @todo: 2-27-2008: Fix how we free up rename mappings 844 // here to alleviate the case for double-freeing registers 845 // in SMT workloads. 846 847 // Unbind Int Regs from Rename Map 848 for (int ireg = 0; ireg < TheISA::NumIntRegs; ireg++) { 849 PhysRegIndex phys_reg = renameMap[tid].lookup(ireg); 850 scoreboard.unsetReg(phys_reg); 851 freeList.addReg(phys_reg); 852 } 853 854 // Unbind Float Regs from Rename Map 855 int max_reg = TheISA::FP_Reg_Base + TheISA::NumFloatRegs; 856 for (int freg = TheISA::FP_Reg_Base; freg < max_reg; freg++) { 857 PhysRegIndex phys_reg = renameMap[tid].lookup(freg); 858 scoreboard.unsetReg(phys_reg); 859 freeList.addReg(phys_reg); 860 } 861 862 // Unbind condition-code Regs from Rename Map 863 max_reg = TheISA::CC_Reg_Base + TheISA::NumCCRegs; 864 for (int creg = TheISA::CC_Reg_Base; creg < max_reg; creg++) { 865 PhysRegIndex phys_reg = renameMap[tid].lookup(creg); 866 scoreboard.unsetReg(phys_reg); 867 freeList.addReg(phys_reg); 868 } 869 870 // Squash Throughout Pipeline 871 DynInstPtr inst = commit.rob->readHeadInst(tid); 872 InstSeqNum squash_seq_num = inst->seqNum; 873 fetch.squash(0, squash_seq_num, inst, tid); 874 decode.squash(tid); 875 rename.squash(squash_seq_num, tid); 876 iew.squash(tid); 877 iew.ldstQueue.squash(squash_seq_num, tid); 878 commit.rob->squash(squash_seq_num, tid); 879 880 881 assert(iew.instQueue.getCount(tid) == 0); 882 assert(iew.ldstQueue.getCount(tid) == 0); 883 884 // Reset ROB/IQ/LSQ Entries 885 886 // Commented out for now. This should be possible to do by 887 // telling all the pipeline stages to drain first, and then 888 // checking until the drain completes. Once the pipeline is 889 // drained, call resetEntries(). - 10-09-06 ktlim 890/* 891 if (activeThreads.size() >= 1) { 892 commit.rob->resetEntries(); 893 iew.resetEntries(); 894 } 895*/ 896} 897 898template <class Impl> 899Fault 900FullO3CPU<Impl>::hwrei(ThreadID tid) 901{ 902#if THE_ISA == ALPHA_ISA 903 // Need to clear the lock flag upon returning from an interrupt. 904 this->setMiscRegNoEffect(AlphaISA::MISCREG_LOCKFLAG, false, tid); 905 906 this->thread[tid]->kernelStats->hwrei(); 907 908 // FIXME: XXX check for interrupts? XXX 909#endif 910 return NoFault; 911} 912 913template <class Impl> 914bool 915FullO3CPU<Impl>::simPalCheck(int palFunc, ThreadID tid) 916{ 917#if THE_ISA == ALPHA_ISA 918 if (this->thread[tid]->kernelStats) 919 this->thread[tid]->kernelStats->callpal(palFunc, 920 this->threadContexts[tid]); 921 922 switch (palFunc) { 923 case PAL::halt: 924 halt(); 925 if (--System::numSystemsRunning == 0) 926 exitSimLoop("all cpus halted"); 927 break; 928 929 case PAL::bpt: 930 case PAL::bugchk: 931 if (this->system->breakpoint()) 932 return false; 933 break; 934 } 935#endif 936 return true; 937} 938 939template <class Impl> 940Fault 941FullO3CPU<Impl>::getInterrupts() 942{ 943 // Check if there are any outstanding interrupts 944 return this->interrupts[0]->getInterrupt(this->threadContexts[0]); 945} 946 947template <class Impl> 948void 949FullO3CPU<Impl>::processInterrupts(const Fault &interrupt) 950{ 951 // Check for interrupts here. For now can copy the code that 952 // exists within isa_fullsys_traits.hh. Also assume that thread 0 953 // is the one that handles the interrupts. 954 // @todo: Possibly consolidate the interrupt checking code. 955 // @todo: Allow other threads to handle interrupts. 956 957 assert(interrupt != NoFault); 958 this->interrupts[0]->updateIntrInfo(this->threadContexts[0]); 959 960 DPRINTF(O3CPU, "Interrupt %s being handled\n", interrupt->name()); 961 this->trap(interrupt, 0, nullptr); 962} 963 964template <class Impl> 965void 966FullO3CPU<Impl>::trap(const Fault &fault, ThreadID tid, 967 const StaticInstPtr &inst) 968{ 969 // Pass the thread's TC into the invoke method. 970 fault->invoke(this->threadContexts[tid], inst); 971} 972 973template <class Impl> 974void 975FullO3CPU<Impl>::syscall(int64_t callnum, ThreadID tid) 976{ 977 DPRINTF(O3CPU, "[tid:%i] Executing syscall().\n\n", tid); 978 979 DPRINTF(Activity,"Activity: syscall() called.\n"); 980 981 // Temporarily increase this by one to account for the syscall 982 // instruction. 983 ++(this->thread[tid]->funcExeInst); 984 985 // Execute the actual syscall. 986 this->thread[tid]->syscall(callnum); 987 988 // Decrease funcExeInst by one as the normal commit will handle 989 // incrementing it. 990 --(this->thread[tid]->funcExeInst); 991} 992 993template <class Impl> 994void 995FullO3CPU<Impl>::serializeThread(CheckpointOut &cp, ThreadID tid) const 996{ 997 thread[tid]->serialize(cp); 998} 999 1000template <class Impl> 1001void 1002FullO3CPU<Impl>::unserializeThread(CheckpointIn &cp, ThreadID tid) 1003{ 1004 thread[tid]->unserialize(cp); 1005} 1006 1007template <class Impl> 1008DrainState 1009FullO3CPU<Impl>::drain() 1010{ 1011 // If the CPU isn't doing anything, then return immediately. 1012 if (switchedOut()) 1013 return DrainState::Drained; 1014 1015 DPRINTF(Drain, "Draining...\n"); 1016 1017 // We only need to signal a drain to the commit stage as this 1018 // initiates squashing controls the draining. Once the commit 1019 // stage commits an instruction where it is safe to stop, it'll 1020 // squash the rest of the instructions in the pipeline and force 1021 // the fetch stage to stall. The pipeline will be drained once all 1022 // in-flight instructions have retired. 1023 commit.drain(); 1024 1025 // Wake the CPU and record activity so everything can drain out if 1026 // the CPU was not able to immediately drain. 1027 if (!isDrained()) { 1028 wakeCPU(); 1029 activityRec.activity(); 1030 1031 DPRINTF(Drain, "CPU not drained\n"); 1032 1033 return DrainState::Draining; 1034 } else { 1035 DPRINTF(Drain, "CPU is already drained\n"); 1036 if (tickEvent.scheduled()) 1037 deschedule(tickEvent); 1038 1039 // Flush out any old data from the time buffers. In 1040 // particular, there might be some data in flight from the 1041 // fetch stage that isn't visible in any of the CPU buffers we 1042 // test in isDrained(). 1043 for (int i = 0; i < timeBuffer.getSize(); ++i) { 1044 timeBuffer.advance(); 1045 fetchQueue.advance(); 1046 decodeQueue.advance(); 1047 renameQueue.advance(); 1048 iewQueue.advance(); 1049 } 1050 1051 drainSanityCheck(); 1052 return DrainState::Drained; 1053 } 1054} 1055 1056template <class Impl> 1057bool 1058FullO3CPU<Impl>::tryDrain() 1059{ 1060 if (drainState() != DrainState::Draining || !isDrained()) 1061 return false; 1062 1063 if (tickEvent.scheduled()) 1064 deschedule(tickEvent); 1065 1066 DPRINTF(Drain, "CPU done draining, processing drain event\n"); 1067 signalDrainDone(); 1068 1069 return true; 1070} 1071 1072template <class Impl> 1073void 1074FullO3CPU<Impl>::drainSanityCheck() const 1075{ 1076 assert(isDrained()); 1077 fetch.drainSanityCheck(); 1078 decode.drainSanityCheck(); 1079 rename.drainSanityCheck(); 1080 iew.drainSanityCheck(); 1081 commit.drainSanityCheck(); 1082} 1083 1084template <class Impl> 1085bool 1086FullO3CPU<Impl>::isDrained() const 1087{ 1088 bool drained(true); 1089 1090 if (!instList.empty() || !removeList.empty()) { 1091 DPRINTF(Drain, "Main CPU structures not drained.\n"); 1092 drained = false; 1093 } 1094 1095 if (!fetch.isDrained()) { 1096 DPRINTF(Drain, "Fetch not drained.\n"); 1097 drained = false; 1098 } 1099 1100 if (!decode.isDrained()) { 1101 DPRINTF(Drain, "Decode not drained.\n"); 1102 drained = false; 1103 } 1104 1105 if (!rename.isDrained()) { 1106 DPRINTF(Drain, "Rename not drained.\n"); 1107 drained = false; 1108 } 1109 1110 if (!iew.isDrained()) { 1111 DPRINTF(Drain, "IEW not drained.\n"); 1112 drained = false; 1113 } 1114 1115 if (!commit.isDrained()) { 1116 DPRINTF(Drain, "Commit not drained.\n"); 1117 drained = false; 1118 } 1119 1120 return drained; 1121} 1122 1123template <class Impl> 1124void 1125FullO3CPU<Impl>::commitDrained(ThreadID tid) 1126{ 1127 fetch.drainStall(tid); 1128} 1129 1130template <class Impl> 1131void 1132FullO3CPU<Impl>::drainResume() 1133{ 1134 if (switchedOut()) 1135 return; 1136 1137 DPRINTF(Drain, "Resuming...\n"); 1138 verifyMemoryMode(); 1139 1140 fetch.drainResume(); 1141 commit.drainResume(); 1142 1143 _status = Idle; 1144 for (ThreadID i = 0; i < thread.size(); i++) { 1145 if (thread[i]->status() == ThreadContext::Active) { 1146 DPRINTF(Drain, "Activating thread: %i\n", i); 1147 activateThread(i); 1148 _status = Running; 1149 } 1150 } 1151 1152 assert(!tickEvent.scheduled()); 1153 if (_status == Running) 1154 schedule(tickEvent, nextCycle()); 1155} 1156 1157template <class Impl> 1158void 1159FullO3CPU<Impl>::switchOut() 1160{ 1161 DPRINTF(O3CPU, "Switching out\n"); 1162 BaseCPU::switchOut(); 1163 1164 activityRec.reset(); 1165 1166 _status = SwitchedOut; 1167 1168 if (checker) 1169 checker->switchOut(); 1170} 1171 1172template <class Impl> 1173void 1174FullO3CPU<Impl>::takeOverFrom(BaseCPU *oldCPU) 1175{ 1176 BaseCPU::takeOverFrom(oldCPU); 1177 1178 fetch.takeOverFrom(); 1179 decode.takeOverFrom(); 1180 rename.takeOverFrom(); 1181 iew.takeOverFrom(); 1182 commit.takeOverFrom(); 1183 1184 assert(!tickEvent.scheduled()); 1185 1186 FullO3CPU<Impl> *oldO3CPU = dynamic_cast<FullO3CPU<Impl>*>(oldCPU); 1187 if (oldO3CPU) 1188 globalSeqNum = oldO3CPU->globalSeqNum; 1189 1190 lastRunningCycle = curCycle(); 1191 _status = Idle; 1192} 1193 1194template <class Impl> 1195void 1196FullO3CPU<Impl>::verifyMemoryMode() const 1197{ 1198 if (!system->isTimingMode()) { 1199 fatal("The O3 CPU requires the memory system to be in " 1200 "'timing' mode.\n"); 1201 } 1202} 1203 1204template <class Impl> 1205TheISA::MiscReg 1206FullO3CPU<Impl>::readMiscRegNoEffect(int misc_reg, ThreadID tid) const 1207{ 1208 return this->isa[tid]->readMiscRegNoEffect(misc_reg); 1209} 1210 1211template <class Impl> 1212TheISA::MiscReg 1213FullO3CPU<Impl>::readMiscReg(int misc_reg, ThreadID tid) 1214{ 1215 miscRegfileReads++; 1216 return this->isa[tid]->readMiscReg(misc_reg, tcBase(tid)); 1217} 1218 1219template <class Impl> 1220void 1221FullO3CPU<Impl>::setMiscRegNoEffect(int misc_reg, 1222 const TheISA::MiscReg &val, ThreadID tid) 1223{ 1224 this->isa[tid]->setMiscRegNoEffect(misc_reg, val); 1225} 1226 1227template <class Impl> 1228void 1229FullO3CPU<Impl>::setMiscReg(int misc_reg, 1230 const TheISA::MiscReg &val, ThreadID tid) 1231{ 1232 miscRegfileWrites++; 1233 this->isa[tid]->setMiscReg(misc_reg, val, tcBase(tid)); 1234} 1235 1236template <class Impl> 1237uint64_t 1238FullO3CPU<Impl>::readIntReg(int reg_idx) 1239{ 1240 intRegfileReads++; 1241 return regFile.readIntReg(reg_idx); 1242} 1243 1244template <class Impl> 1245FloatReg 1246FullO3CPU<Impl>::readFloatReg(int reg_idx) 1247{ 1248 fpRegfileReads++; 1249 return regFile.readFloatReg(reg_idx); 1250} 1251 1252template <class Impl> 1253FloatRegBits 1254FullO3CPU<Impl>::readFloatRegBits(int reg_idx) 1255{ 1256 fpRegfileReads++; 1257 return regFile.readFloatRegBits(reg_idx); 1258} 1259 1260template <class Impl> 1261CCReg 1262FullO3CPU<Impl>::readCCReg(int reg_idx) 1263{ 1264 ccRegfileReads++; 1265 return regFile.readCCReg(reg_idx); 1266} 1267 1268template <class Impl> 1269void 1270FullO3CPU<Impl>::setIntReg(int reg_idx, uint64_t val) 1271{ 1272 intRegfileWrites++; 1273 regFile.setIntReg(reg_idx, val); 1274} 1275 1276template <class Impl> 1277void 1278FullO3CPU<Impl>::setFloatReg(int reg_idx, FloatReg val) 1279{ 1280 fpRegfileWrites++; 1281 regFile.setFloatReg(reg_idx, val); 1282} 1283 1284template <class Impl> 1285void 1286FullO3CPU<Impl>::setFloatRegBits(int reg_idx, FloatRegBits val) 1287{ 1288 fpRegfileWrites++; 1289 regFile.setFloatRegBits(reg_idx, val); 1290} 1291 1292template <class Impl> 1293void 1294FullO3CPU<Impl>::setCCReg(int reg_idx, CCReg val) 1295{ 1296 ccRegfileWrites++; 1297 regFile.setCCReg(reg_idx, val); 1298} 1299 1300template <class Impl> 1301uint64_t 1302FullO3CPU<Impl>::readArchIntReg(int reg_idx, ThreadID tid) 1303{ 1304 intRegfileReads++; 1305 PhysRegIndex phys_reg = commitRenameMap[tid].lookupInt(reg_idx); 1306 1307 return regFile.readIntReg(phys_reg); 1308} 1309 1310template <class Impl> 1311float 1312FullO3CPU<Impl>::readArchFloatReg(int reg_idx, ThreadID tid) 1313{ 1314 fpRegfileReads++; 1315 PhysRegIndex phys_reg = commitRenameMap[tid].lookupFloat(reg_idx); 1316 1317 return regFile.readFloatReg(phys_reg); 1318} 1319 1320template <class Impl> 1321uint64_t 1322FullO3CPU<Impl>::readArchFloatRegInt(int reg_idx, ThreadID tid) 1323{ 1324 fpRegfileReads++; 1325 PhysRegIndex phys_reg = commitRenameMap[tid].lookupFloat(reg_idx); 1326 1327 return regFile.readFloatRegBits(phys_reg); 1328} 1329 1330template <class Impl> 1331CCReg 1332FullO3CPU<Impl>::readArchCCReg(int reg_idx, ThreadID tid) 1333{ 1334 ccRegfileReads++; 1335 PhysRegIndex phys_reg = commitRenameMap[tid].lookupCC(reg_idx); 1336 1337 return regFile.readCCReg(phys_reg); 1338} 1339 1340template <class Impl> 1341void 1342FullO3CPU<Impl>::setArchIntReg(int reg_idx, uint64_t val, ThreadID tid) 1343{ 1344 intRegfileWrites++; 1345 PhysRegIndex phys_reg = commitRenameMap[tid].lookupInt(reg_idx); 1346 1347 regFile.setIntReg(phys_reg, val); 1348} 1349 1350template <class Impl> 1351void 1352FullO3CPU<Impl>::setArchFloatReg(int reg_idx, float val, ThreadID tid) 1353{ 1354 fpRegfileWrites++; 1355 PhysRegIndex phys_reg = commitRenameMap[tid].lookupFloat(reg_idx); 1356 1357 regFile.setFloatReg(phys_reg, val); 1358} 1359 1360template <class Impl> 1361void 1362FullO3CPU<Impl>::setArchFloatRegInt(int reg_idx, uint64_t val, ThreadID tid) 1363{ 1364 fpRegfileWrites++; 1365 PhysRegIndex phys_reg = commitRenameMap[tid].lookupFloat(reg_idx); 1366 1367 regFile.setFloatRegBits(phys_reg, val); 1368} 1369 1370template <class Impl> 1371void 1372FullO3CPU<Impl>::setArchCCReg(int reg_idx, CCReg val, ThreadID tid) 1373{ 1374 ccRegfileWrites++; 1375 PhysRegIndex phys_reg = commitRenameMap[tid].lookupCC(reg_idx); 1376 1377 regFile.setCCReg(phys_reg, val); 1378} 1379 1380template <class Impl> 1381TheISA::PCState 1382FullO3CPU<Impl>::pcState(ThreadID tid) 1383{ 1384 return commit.pcState(tid); 1385} 1386 1387template <class Impl> 1388void 1389FullO3CPU<Impl>::pcState(const TheISA::PCState &val, ThreadID tid) 1390{ 1391 commit.pcState(val, tid); 1392} 1393 1394template <class Impl> 1395Addr 1396FullO3CPU<Impl>::instAddr(ThreadID tid) 1397{ 1398 return commit.instAddr(tid); 1399} 1400 1401template <class Impl> 1402Addr 1403FullO3CPU<Impl>::nextInstAddr(ThreadID tid) 1404{ 1405 return commit.nextInstAddr(tid); 1406} 1407 1408template <class Impl> 1409MicroPC 1410FullO3CPU<Impl>::microPC(ThreadID tid) 1411{ 1412 return commit.microPC(tid); 1413} 1414 1415template <class Impl> 1416void 1417FullO3CPU<Impl>::squashFromTC(ThreadID tid) 1418{ 1419 this->thread[tid]->noSquashFromTC = true; 1420 this->commit.generateTCEvent(tid); 1421} 1422 1423template <class Impl> 1424typename FullO3CPU<Impl>::ListIt 1425FullO3CPU<Impl>::addInst(DynInstPtr &inst) 1426{ 1427 instList.push_back(inst); 1428 1429 return --(instList.end()); 1430} 1431 1432template <class Impl> 1433void 1434FullO3CPU<Impl>::instDone(ThreadID tid, DynInstPtr &inst) 1435{ 1436 // Keep an instruction count. 1437 if (!inst->isMicroop() || inst->isLastMicroop()) { 1438 thread[tid]->numInst++; 1439 thread[tid]->numInsts++; 1440 committedInsts[tid]++; 1441 system->totalNumInsts++; 1442 1443 // Check for instruction-count-based events. 1444 comInstEventQueue[tid]->serviceEvents(thread[tid]->numInst); 1445 system->instEventQueue.serviceEvents(system->totalNumInsts); 1446 } 1447 thread[tid]->numOp++; 1448 thread[tid]->numOps++; 1449 committedOps[tid]++; 1450 1451 probeInstCommit(inst->staticInst); 1452} 1453 1454template <class Impl> 1455void 1456FullO3CPU<Impl>::removeFrontInst(DynInstPtr &inst) 1457{ 1458 DPRINTF(O3CPU, "Removing committed instruction [tid:%i] PC %s " 1459 "[sn:%lli]\n", 1460 inst->threadNumber, inst->pcState(), inst->seqNum); 1461 1462 removeInstsThisCycle = true; 1463 1464 // Remove the front instruction. 1465 removeList.push(inst->getInstListIt()); 1466} 1467 1468template <class Impl> 1469void 1470FullO3CPU<Impl>::removeInstsNotInROB(ThreadID tid) 1471{ 1472 DPRINTF(O3CPU, "Thread %i: Deleting instructions from instruction" 1473 " list.\n", tid); 1474 1475 ListIt end_it; 1476 1477 bool rob_empty = false; 1478 1479 if (instList.empty()) { 1480 return; 1481 } else if (rob.isEmpty(tid)) { 1482 DPRINTF(O3CPU, "ROB is empty, squashing all insts.\n"); 1483 end_it = instList.begin(); 1484 rob_empty = true; 1485 } else { 1486 end_it = (rob.readTailInst(tid))->getInstListIt(); 1487 DPRINTF(O3CPU, "ROB is not empty, squashing insts not in ROB.\n"); 1488 } 1489 1490 removeInstsThisCycle = true; 1491 1492 ListIt inst_it = instList.end(); 1493 1494 inst_it--; 1495 1496 // Walk through the instruction list, removing any instructions 1497 // that were inserted after the given instruction iterator, end_it. 1498 while (inst_it != end_it) { 1499 assert(!instList.empty()); 1500 1501 squashInstIt(inst_it, tid); 1502 1503 inst_it--; 1504 } 1505 1506 // If the ROB was empty, then we actually need to remove the first 1507 // instruction as well. 1508 if (rob_empty) { 1509 squashInstIt(inst_it, tid); 1510 } 1511} 1512 1513template <class Impl> 1514void 1515FullO3CPU<Impl>::removeInstsUntil(const InstSeqNum &seq_num, ThreadID tid) 1516{ 1517 assert(!instList.empty()); 1518 1519 removeInstsThisCycle = true; 1520 1521 ListIt inst_iter = instList.end(); 1522 1523 inst_iter--; 1524 1525 DPRINTF(O3CPU, "Deleting instructions from instruction " 1526 "list that are from [tid:%i] and above [sn:%lli] (end=%lli).\n", 1527 tid, seq_num, (*inst_iter)->seqNum); 1528 1529 while ((*inst_iter)->seqNum > seq_num) { 1530 1531 bool break_loop = (inst_iter == instList.begin()); 1532 1533 squashInstIt(inst_iter, tid); 1534 1535 inst_iter--; 1536 1537 if (break_loop) 1538 break; 1539 } 1540} 1541 1542template <class Impl> 1543inline void 1544FullO3CPU<Impl>::squashInstIt(const ListIt &instIt, ThreadID tid) 1545{ 1546 if ((*instIt)->threadNumber == tid) { 1547 DPRINTF(O3CPU, "Squashing instruction, " 1548 "[tid:%i] [sn:%lli] PC %s\n", 1549 (*instIt)->threadNumber, 1550 (*instIt)->seqNum, 1551 (*instIt)->pcState()); 1552 1553 // Mark it as squashed. 1554 (*instIt)->setSquashed(); 1555 1556 // @todo: Formulate a consistent method for deleting 1557 // instructions from the instruction list 1558 // Remove the instruction from the list. 1559 removeList.push(instIt); 1560 } 1561} 1562 1563template <class Impl> 1564void 1565FullO3CPU<Impl>::cleanUpRemovedInsts() 1566{ 1567 while (!removeList.empty()) { 1568 DPRINTF(O3CPU, "Removing instruction, " 1569 "[tid:%i] [sn:%lli] PC %s\n", 1570 (*removeList.front())->threadNumber, 1571 (*removeList.front())->seqNum, 1572 (*removeList.front())->pcState()); 1573 1574 instList.erase(removeList.front()); 1575 1576 removeList.pop(); 1577 } 1578 1579 removeInstsThisCycle = false; 1580} 1581/* 1582template <class Impl> 1583void 1584FullO3CPU<Impl>::removeAllInsts() 1585{ 1586 instList.clear(); 1587} 1588*/ 1589template <class Impl> 1590void 1591FullO3CPU<Impl>::dumpInsts() 1592{ 1593 int num = 0; 1594 1595 ListIt inst_list_it = instList.begin(); 1596 1597 cprintf("Dumping Instruction List\n"); 1598 1599 while (inst_list_it != instList.end()) { 1600 cprintf("Instruction:%i\nPC:%#x\n[tid:%i]\n[sn:%lli]\nIssued:%i\n" 1601 "Squashed:%i\n\n", 1602 num, (*inst_list_it)->instAddr(), (*inst_list_it)->threadNumber, 1603 (*inst_list_it)->seqNum, (*inst_list_it)->isIssued(), 1604 (*inst_list_it)->isSquashed()); 1605 inst_list_it++; 1606 ++num; 1607 } 1608} 1609/* 1610template <class Impl> 1611void 1612FullO3CPU<Impl>::wakeDependents(DynInstPtr &inst) 1613{ 1614 iew.wakeDependents(inst); 1615} 1616*/ 1617template <class Impl> 1618void 1619FullO3CPU<Impl>::wakeCPU() 1620{ 1621 if (activityRec.active() || tickEvent.scheduled()) { 1622 DPRINTF(Activity, "CPU already running.\n"); 1623 return; 1624 } 1625 1626 DPRINTF(Activity, "Waking up CPU\n"); 1627 1628 Cycles cycles(curCycle() - lastRunningCycle); 1629 // @todo: This is an oddity that is only here to match the stats 1630 if (cycles > 1) { 1631 --cycles; 1632 idleCycles += cycles; 1633 numCycles += cycles; 1634 ppCycles->notify(cycles); 1635 } 1636 1637 schedule(tickEvent, clockEdge()); 1638} 1639 1640template <class Impl> 1641void 1642FullO3CPU<Impl>::wakeup(ThreadID tid) 1643{ 1644 if (this->thread[tid]->status() != ThreadContext::Suspended) 1645 return; 1646 1647 this->wakeCPU(); 1648 1649 DPRINTF(Quiesce, "Suspended Processor woken\n"); 1650 this->threadContexts[tid]->activate(); 1651} 1652 1653template <class Impl> 1654ThreadID 1655FullO3CPU<Impl>::getFreeTid() 1656{ 1657 for (ThreadID tid = 0; tid < numThreads; tid++) { 1658 if (!tids[tid]) { 1659 tids[tid] = true; 1660 return tid; 1661 } 1662 } 1663 1664 return InvalidThreadID; 1665} 1666 1667template <class Impl> 1668void 1669FullO3CPU<Impl>::updateThreadPriority() 1670{ 1671 if (activeThreads.size() > 1) { 1672 //DEFAULT TO ROUND ROBIN SCHEME 1673 //e.g. Move highest priority to end of thread list 1674 list<ThreadID>::iterator list_begin = activeThreads.begin(); 1675 1676 unsigned high_thread = *list_begin; 1677 1678 activeThreads.erase(list_begin); 1679 1680 activeThreads.push_back(high_thread); 1681 } 1682} 1683 1684// Forward declaration of FullO3CPU. 1685template class FullO3CPU<O3CPUImpl>;
|