cpu.cc revision 2356
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 29#include "config/full_system.hh" 30 31#if FULL_SYSTEM 32#include "cpu/quiesce_event.hh" 33#include "sim/system.hh" 34#else 35#include "sim/process.hh" 36#endif 37 38#include "cpu/activity.hh" 39#include "cpu/checker/cpu.hh" 40#include "cpu/cpu_exec_context.hh" 41#include "cpu/exec_context.hh" 42#include "cpu/o3/alpha_dyn_inst.hh" 43#include "cpu/o3/alpha_impl.hh" 44#include "cpu/o3/cpu.hh" 45 46#include "sim/root.hh" 47#include "sim/stat_control.hh" 48 49using namespace std; 50 51BaseFullCPU::BaseFullCPU(Params *params) 52 : BaseCPU(params), cpu_id(0) 53{ 54} 55 56void 57BaseFullCPU::regStats() 58{ 59 BaseCPU::regStats(); 60} 61 62template <class Impl> 63FullO3CPU<Impl>::TickEvent::TickEvent(FullO3CPU<Impl> *c) 64 : Event(&mainEventQueue, CPU_Tick_Pri), cpu(c) 65{ 66} 67 68template <class Impl> 69void 70FullO3CPU<Impl>::TickEvent::process() 71{ 72 cpu->tick(); 73} 74 75template <class Impl> 76const char * 77FullO3CPU<Impl>::TickEvent::description() 78{ 79 return "FullO3CPU tick event"; 80} 81 82template <class Impl> 83FullO3CPU<Impl>::FullO3CPU(Params *params) 84 : BaseFullCPU(params), 85 tickEvent(this), 86 removeInstsThisCycle(false), 87 fetch(params), 88 decode(params), 89 rename(params), 90 iew(params), 91 commit(params), 92 93 regFile(params->numPhysIntRegs, params->numPhysFloatRegs), 94 95 freeList(params->numberOfThreads,//number of activeThreads 96 TheISA::NumIntRegs, params->numPhysIntRegs, 97 TheISA::NumFloatRegs, params->numPhysFloatRegs), 98 99 rob(params->numROBEntries, params->squashWidth, 100 params->smtROBPolicy, params->smtROBThreshold, 101 params->numberOfThreads), 102 103 scoreboard(params->numberOfThreads,//number of activeThreads 104 TheISA::NumIntRegs, params->numPhysIntRegs, 105 TheISA::NumFloatRegs, params->numPhysFloatRegs, 106 TheISA::NumMiscRegs * number_of_threads, 107 TheISA::ZeroReg), 108 109 // For now just have these time buffers be pretty big. 110 // @todo: Make these time buffer sizes parameters or derived 111 // from latencies 112 timeBuffer(params->backComSize, params->forwardComSize), 113 fetchQueue(params->backComSize, params->forwardComSize), 114 decodeQueue(params->backComSize, params->forwardComSize), 115 renameQueue(params->backComSize, params->forwardComSize), 116 iewQueue(params->backComSize, params->forwardComSize), 117 activityRec(NumStages, 118 params->backComSize + params->forwardComSize, 119 params->activity), 120 121 globalSeqNum(1), 122 123#if FULL_SYSTEM 124 system(params->system), 125 memCtrl(system->memctrl), 126 physmem(system->physmem), 127 mem(params->mem), 128#else 129// pTable(params->pTable), 130 mem(params->workload[0]->getMemory()), 131#endif // FULL_SYSTEM 132 switchCount(0), 133 icacheInterface(params->icacheInterface), 134 dcacheInterface(params->dcacheInterface), 135 deferRegistration(params->deferRegistration), 136 numThreads(number_of_threads) 137{ 138 _status = Idle; 139 140 if (params->checker) { 141 BaseCPU *temp_checker = params->checker; 142 checker = dynamic_cast<Checker<DynInstPtr> *>(temp_checker); 143 checker->setMemory(mem); 144#if FULL_SYSTEM 145 checker->setSystem(params->system); 146#endif 147 } else { 148 checker = NULL; 149 } 150 151#if !FULL_SYSTEM 152 thread.resize(number_of_threads); 153 tids.resize(number_of_threads); 154#endif 155 156 // The stages also need their CPU pointer setup. However this 157 // must be done at the upper level CPU because they have pointers 158 // to the upper level CPU, and not this FullO3CPU. 159 160 // Set up Pointers to the activeThreads list for each stage 161 fetch.setActiveThreads(&activeThreads); 162 decode.setActiveThreads(&activeThreads); 163 rename.setActiveThreads(&activeThreads); 164 iew.setActiveThreads(&activeThreads); 165 commit.setActiveThreads(&activeThreads); 166 167 // Give each of the stages the time buffer they will use. 168 fetch.setTimeBuffer(&timeBuffer); 169 decode.setTimeBuffer(&timeBuffer); 170 rename.setTimeBuffer(&timeBuffer); 171 iew.setTimeBuffer(&timeBuffer); 172 commit.setTimeBuffer(&timeBuffer); 173 174 // Also setup each of the stages' queues. 175 fetch.setFetchQueue(&fetchQueue); 176 decode.setFetchQueue(&fetchQueue); 177 commit.setFetchQueue(&fetchQueue); 178 decode.setDecodeQueue(&decodeQueue); 179 rename.setDecodeQueue(&decodeQueue); 180 rename.setRenameQueue(&renameQueue); 181 iew.setRenameQueue(&renameQueue); 182 iew.setIEWQueue(&iewQueue); 183 commit.setIEWQueue(&iewQueue); 184 commit.setRenameQueue(&renameQueue); 185 186 commit.setIEWStage(&iew); 187 rename.setIEWStage(&iew); 188 rename.setCommitStage(&commit); 189 190#if !FULL_SYSTEM 191 int active_threads = params->workload.size(); 192#else 193 int active_threads = 1; 194#endif 195 196 //Make Sure That this a Valid Architeture 197 assert(params->numPhysIntRegs >= numThreads * TheISA::NumIntRegs); 198 assert(params->numPhysFloatRegs >= numThreads * TheISA::NumFloatRegs); 199 200 rename.setScoreboard(&scoreboard); 201 iew.setScoreboard(&scoreboard); 202 203 // Setup the rename map for whichever stages need it. 204 PhysRegIndex lreg_idx = 0; 205 PhysRegIndex freg_idx = params->numPhysIntRegs; //Index to 1 after int regs 206 207 for (int tid=0; tid < numThreads; tid++) { 208 bool bindRegs = (tid <= active_threads - 1); 209 210 commitRenameMap[tid].init(TheISA::NumIntRegs, 211 params->numPhysIntRegs, 212 lreg_idx, //Index for Logical. Regs 213 214 TheISA::NumFloatRegs, 215 params->numPhysFloatRegs, 216 freg_idx, //Index for Float Regs 217 218 TheISA::NumMiscRegs, 219 220 TheISA::ZeroReg, 221 TheISA::ZeroReg, 222 223 tid, 224 false); 225 226 renameMap[tid].init(TheISA::NumIntRegs, 227 params->numPhysIntRegs, 228 lreg_idx, //Index for Logical. Regs 229 230 TheISA::NumFloatRegs, 231 params->numPhysFloatRegs, 232 freg_idx, //Index for Float Regs 233 234 TheISA::NumMiscRegs, 235 236 TheISA::ZeroReg, 237 TheISA::ZeroReg, 238 239 tid, 240 bindRegs); 241 } 242 243 rename.setRenameMap(renameMap); 244 commit.setRenameMap(commitRenameMap); 245 246 // Give renameMap & rename stage access to the freeList; 247 for (int i=0; i < numThreads; i++) { 248 renameMap[i].setFreeList(&freeList); 249 } 250 rename.setFreeList(&freeList); 251 252 // Setup the page table for whichever stages need it. 253#if !FULL_SYSTEM 254// fetch.setPageTable(pTable); 255// iew.setPageTable(pTable); 256#endif 257 258 // Setup the ROB for whichever stages need it. 259 commit.setROB(&rob); 260 261 lastRunningCycle = curTick; 262 263 contextSwitch = false; 264} 265 266template <class Impl> 267FullO3CPU<Impl>::~FullO3CPU() 268{ 269} 270 271template <class Impl> 272void 273FullO3CPU<Impl>::fullCPURegStats() 274{ 275 BaseFullCPU::regStats(); 276 277 // Register any of the FullCPU's stats here. 278 timesIdled 279 .name(name() + ".timesIdled") 280 .desc("Number of times that the entire CPU went into an idle state and" 281 " unscheduled itself") 282 .prereq(timesIdled); 283 284 idleCycles 285 .name(name() + ".idleCycles") 286 .desc("Total number of cycles that the CPU has spent unscheduled due " 287 "to idling") 288 .prereq(idleCycles); 289 290 // Number of Instructions simulated 291 // -------------------------------- 292 // Should probably be in Base CPU but need templated 293 // MaxThreads so put in here instead 294 committedInsts 295 .init(numThreads) 296 .name(name() + ".committedInsts") 297 .desc("Number of Instructions Simulated"); 298 299 totalCommittedInsts 300 .name(name() + ".committedInsts_total") 301 .desc("Number of Instructions Simulated"); 302 303 cpi 304 .name(name() + ".cpi") 305 .desc("CPI: Cycles Per Instruction") 306 .precision(6); 307 cpi = simTicks / committedInsts; 308 309 totalCpi 310 .name(name() + ".cpi_total") 311 .desc("CPI: Total CPI of All Threads") 312 .precision(6); 313 totalCpi = simTicks / totalCommittedInsts; 314 315 ipc 316 .name(name() + ".ipc") 317 .desc("IPC: Instructions Per Cycle") 318 .precision(6); 319 ipc = committedInsts / simTicks; 320 321 totalIpc 322 .name(name() + ".ipc_total") 323 .desc("IPC: Total IPC of All Threads") 324 .precision(6); 325 totalIpc = totalCommittedInsts / simTicks; 326 327} 328 329template <class Impl> 330void 331FullO3CPU<Impl>::tick() 332{ 333 DPRINTF(FullCPU, "\n\nFullCPU: Ticking main, FullO3CPU.\n"); 334 335 ++numCycles; 336 337// activity = false; 338 339 //Tick each of the stages 340 fetch.tick(); 341 342 decode.tick(); 343 344 rename.tick(); 345 346 iew.tick(); 347 348 commit.tick(); 349 350#if !FULL_SYSTEM 351 doContextSwitch(); 352#endif 353 354 // Now advance the time buffers 355 timeBuffer.advance(); 356 357 fetchQueue.advance(); 358 decodeQueue.advance(); 359 renameQueue.advance(); 360 iewQueue.advance(); 361 362 activityRec.advance(); 363 364 if (removeInstsThisCycle) { 365 cleanUpRemovedInsts(); 366 } 367 368 if (!tickEvent.scheduled()) { 369 if (_status == SwitchedOut) { 370 // increment stat 371 lastRunningCycle = curTick; 372 } else if (!activityRec.active()) { 373 lastRunningCycle = curTick; 374 timesIdled++; 375 } else { 376 tickEvent.schedule(curTick + cycles(1)); 377 } 378 } 379 380#if !FULL_SYSTEM 381 updateThreadPriority(); 382#endif 383 384} 385 386template <class Impl> 387void 388FullO3CPU<Impl>::init() 389{ 390 if (!deferRegistration) { 391 registerExecContexts(); 392 } 393 394 // Set inSyscall so that the CPU doesn't squash when initially 395 // setting up registers. 396 for (int i = 0; i < number_of_threads; ++i) 397 thread[i]->inSyscall = true; 398 399 for (int tid=0; tid < number_of_threads; tid++) { 400#if FULL_SYSTEM 401 ExecContext *src_xc = execContexts[tid]; 402#else 403 ExecContext *src_xc = thread[tid]->getXCProxy(); 404#endif 405 // Threads start in the Suspended State 406 if (src_xc->status() != ExecContext::Suspended) { 407 continue; 408 } 409 410#if FULL_SYSTEM 411 TheISA::initCPU(src_xc, src_xc->readCpuId()); 412#endif 413 } 414 415 // Clear inSyscall. 416 for (int i = 0; i < number_of_threads; ++i) 417 thread[i]->inSyscall = false; 418 419 // Initialize stages. 420 fetch.initStage(); 421 iew.initStage(); 422 rename.initStage(); 423 commit.initStage(); 424 425 commit.setThreads(thread); 426} 427 428template <class Impl> 429void 430FullO3CPU<Impl>::insertThread(unsigned tid) 431{ 432 DPRINTF(FullCPU,"[tid:%i] Initializing thread data"); 433 // Will change now that the PC and thread state is internal to the CPU 434 // and not in the CPUExecContext. 435#if 0 436#if FULL_SYSTEM 437 ExecContext *src_xc = system->execContexts[tid]; 438#else 439 CPUExecContext *src_xc = thread[tid]; 440#endif 441 442 //Bind Int Regs to Rename Map 443 for (int ireg = 0; ireg < TheISA::NumIntRegs; ireg++) { 444 PhysRegIndex phys_reg = freeList.getIntReg(); 445 446 renameMap[tid].setEntry(ireg,phys_reg); 447 scoreboard.setReg(phys_reg); 448 } 449 450 //Bind Float Regs to Rename Map 451 for (int freg = 0; freg < TheISA::NumFloatRegs; freg++) { 452 PhysRegIndex phys_reg = freeList.getFloatReg(); 453 454 renameMap[tid].setEntry(freg,phys_reg); 455 scoreboard.setReg(phys_reg); 456 } 457 458 //Copy Thread Data Into RegFile 459 this->copyFromXC(tid); 460 461 //Set PC/NPC 462 regFile.pc[tid] = src_xc->readPC(); 463 regFile.npc[tid] = src_xc->readNextPC(); 464 465 src_xc->setStatus(ExecContext::Active); 466 467 activateContext(tid,1); 468 469 //Reset ROB/IQ/LSQ Entries 470 commit.rob->resetEntries(); 471 iew.resetEntries(); 472#endif 473} 474 475template <class Impl> 476void 477FullO3CPU<Impl>::removeThread(unsigned tid) 478{ 479 DPRINTF(FullCPU,"[tid:%i] Removing thread data"); 480#if 0 481 //Unbind Int Regs from Rename Map 482 for (int ireg = 0; ireg < TheISA::NumIntRegs; ireg++) { 483 PhysRegIndex phys_reg = renameMap[tid].lookup(ireg); 484 485 scoreboard.unsetReg(phys_reg); 486 freeList.addReg(phys_reg); 487 } 488 489 //Unbind Float Regs from Rename Map 490 for (int freg = 0; freg < TheISA::NumFloatRegs; freg++) { 491 PhysRegIndex phys_reg = renameMap[tid].lookup(freg); 492 493 scoreboard.unsetReg(phys_reg); 494 freeList.addReg(phys_reg); 495 } 496 497 //Copy Thread Data From RegFile 498 /* Fix Me: 499 * Do we really need to do this if we are removing a thread 500 * in the sense that it's finished (exiting)? If the thread is just 501 * being suspended we might... 502 */ 503// this->copyToXC(tid); 504 505 //Squash Throughout Pipeline 506 fetch.squash(0,tid); 507 decode.squash(tid); 508 rename.squash(tid); 509 510 assert(iew.ldstQueue.getCount(tid) == 0); 511 512 //Reset ROB/IQ/LSQ Entries 513 if (activeThreads.size() >= 1) { 514 commit.rob->resetEntries(); 515 iew.resetEntries(); 516 } 517#endif 518} 519 520 521template <class Impl> 522void 523FullO3CPU<Impl>::activateWhenReady(int tid) 524{ 525 DPRINTF(FullCPU,"[tid:%i]: Checking if resources are available for incoming" 526 "(e.g. PhysRegs/ROB/IQ/LSQ) \n", 527 tid); 528 529 bool ready = true; 530 531 if (freeList.numFreeIntRegs() >= TheISA::NumIntRegs) { 532 DPRINTF(FullCPU,"[tid:%i] Suspending thread due to not enough " 533 "Phys. Int. Regs.\n", 534 tid); 535 ready = false; 536 } else if (freeList.numFreeFloatRegs() >= TheISA::NumFloatRegs) { 537 DPRINTF(FullCPU,"[tid:%i] Suspending thread due to not enough " 538 "Phys. Float. Regs.\n", 539 tid); 540 ready = false; 541 } else if (commit.rob->numFreeEntries() >= 542 commit.rob->entryAmount(activeThreads.size() + 1)) { 543 DPRINTF(FullCPU,"[tid:%i] Suspending thread due to not enough " 544 "ROB entries.\n", 545 tid); 546 ready = false; 547 } else if (iew.instQueue.numFreeEntries() >= 548 iew.instQueue.entryAmount(activeThreads.size() + 1)) { 549 DPRINTF(FullCPU,"[tid:%i] Suspending thread due to not enough " 550 "IQ entries.\n", 551 tid); 552 ready = false; 553 } else if (iew.ldstQueue.numFreeEntries() >= 554 iew.ldstQueue.entryAmount(activeThreads.size() + 1)) { 555 DPRINTF(FullCPU,"[tid:%i] Suspending thread due to not enough " 556 "LSQ entries.\n", 557 tid); 558 ready = false; 559 } 560 561 if (ready) { 562 insertThread(tid); 563 564 contextSwitch = false; 565 566 cpuWaitList.remove(tid); 567 } else { 568 suspendContext(tid); 569 570 //blocks fetch 571 contextSwitch = true; 572 573 //do waitlist 574 cpuWaitList.push_back(tid); 575 } 576} 577 578template <class Impl> 579void 580FullO3CPU<Impl>::activateContext(int tid, int delay) 581{ 582 // Needs to set each stage to running as well. 583 list<unsigned>::iterator isActive = find( 584 activeThreads.begin(), activeThreads.end(), tid); 585 586 if (isActive == activeThreads.end()) { 587 //May Need to Re-code this if the delay variable is the 588 //delay needed for thread to activate 589 DPRINTF(FullCPU, "Adding Thread %i to active threads list\n", 590 tid); 591 592 activeThreads.push_back(tid); 593 } 594 595 assert(_status == Idle || _status == SwitchedOut); 596 597 scheduleTickEvent(delay); 598 599 // Be sure to signal that there's some activity so the CPU doesn't 600 // deschedule itself. 601 activityRec.activity(); 602 if (thread[tid]->quiesceEvent && thread[tid]->quiesceEvent->scheduled()) 603 thread[tid]->quiesceEvent->deschedule(); 604 605 fetch.wakeFromQuiesce(); 606 607 _status = Running; 608} 609 610template <class Impl> 611void 612FullO3CPU<Impl>::suspendContext(int tid) 613{ 614 DPRINTF(FullCPU,"[tid: %i]: Suspended ...\n", tid); 615 unscheduleTickEvent(); 616 _status = Idle; 617/* 618 //Remove From Active List, if Active 619 list<unsigned>::iterator isActive = find( 620 activeThreads.begin(), activeThreads.end(), tid); 621 622 if (isActive != activeThreads.end()) { 623 DPRINTF(FullCPU,"[tid:%i]: Removing from active threads list\n", 624 tid); 625 activeThreads.erase(isActive); 626 } 627*/ 628} 629 630template <class Impl> 631void 632FullO3CPU<Impl>::deallocateContext(int tid) 633{ 634 DPRINTF(FullCPU,"[tid:%i]: Deallocating ...", tid); 635/* 636 //Remove From Active List, if Active 637 list<unsigned>::iterator isActive = find( 638 activeThreads.begin(), activeThreads.end(), tid); 639 640 if (isActive != activeThreads.end()) { 641 DPRINTF(FullCPU,"[tid:%i]: Removing from active threads list\n", 642 tid); 643 activeThreads.erase(isActive); 644 645 removeThread(tid); 646 } 647*/ 648} 649 650template <class Impl> 651void 652FullO3CPU<Impl>::haltContext(int tid) 653{ 654 DPRINTF(FullCPU,"[tid:%i]: Halted ...", tid); 655/* 656 //Remove From Active List, if Active 657 list<unsigned>::iterator isActive = find( 658 activeThreads.begin(), activeThreads.end(), tid); 659 660 if (isActive != activeThreads.end()) { 661 DPRINTF(FullCPU,"[tid:%i]: Removing from active threads list\n", 662 tid); 663 activeThreads.erase(isActive); 664 665 removeThread(tid); 666 } 667*/ 668} 669 670template <class Impl> 671void 672FullO3CPU<Impl>::switchOut(Sampler *_sampler) 673{ 674 sampler = _sampler; 675 switchCount = 0; 676 fetch.switchOut(); 677 decode.switchOut(); 678 rename.switchOut(); 679 iew.switchOut(); 680 commit.switchOut(); 681 682 // Wake the CPU and record activity so everything can drain out if 683 // the CPU is currently idle. 684 wakeCPU(); 685 activityRec.activity(); 686} 687 688template <class Impl> 689void 690FullO3CPU<Impl>::signalSwitched() 691{ 692 if (++switchCount == NumStages) { 693 fetch.doSwitchOut(); 694 rename.doSwitchOut(); 695 commit.doSwitchOut(); 696 instList.clear(); 697 while (!removeList.empty()) { 698 removeList.pop(); 699 } 700 701 if (checker) 702 checker->switchOut(sampler); 703 704 if (tickEvent.scheduled()) 705 tickEvent.squash(); 706 sampler->signalSwitched(); 707 _status = SwitchedOut; 708 } 709 assert(switchCount <= 5); 710} 711 712template <class Impl> 713void 714FullO3CPU<Impl>::takeOverFrom(BaseCPU *oldCPU) 715{ 716 // Flush out any old data from the time buffers. 717 for (int i = 0; i < timeBuffer.getSize(); ++i) { 718 timeBuffer.advance(); 719 fetchQueue.advance(); 720 decodeQueue.advance(); 721 renameQueue.advance(); 722 iewQueue.advance(); 723 } 724 725 activityRec.reset(); 726 727 BaseCPU::takeOverFrom(oldCPU); 728 729 fetch.takeOverFrom(); 730 decode.takeOverFrom(); 731 rename.takeOverFrom(); 732 iew.takeOverFrom(); 733 commit.takeOverFrom(); 734 735 assert(!tickEvent.scheduled()); 736 737 // @todo: Figure out how to properly select the tid to put onto 738 // the active threads list. 739 int tid = 0; 740 741 list<unsigned>::iterator isActive = find( 742 activeThreads.begin(), activeThreads.end(), tid); 743 744 if (isActive == activeThreads.end()) { 745 //May Need to Re-code this if the delay variable is the delay 746 //needed for thread to activate 747 DPRINTF(FullCPU, "Adding Thread %i to active threads list\n", 748 tid); 749 750 activeThreads.push_back(tid); 751 } 752 753 // Set all statuses to active, schedule the CPU's tick event. 754 // @todo: Fix up statuses so this is handled properly 755 for (int i = 0; i < execContexts.size(); ++i) { 756 ExecContext *xc = execContexts[i]; 757 if (xc->status() == ExecContext::Active && _status != Running) { 758 _status = Running; 759 tickEvent.schedule(curTick); 760 } 761 } 762 if (!tickEvent.scheduled()) 763 tickEvent.schedule(curTick); 764} 765 766template <class Impl> 767void 768FullO3CPU<Impl>::serialize(std::ostream &os) 769{ 770 BaseCPU::serialize(os); 771 nameOut(os, csprintf("%s.tickEvent", name())); 772 tickEvent.serialize(os); 773 774 // Use SimpleThread's ability to checkpoint to make it easier to 775 // write out the registers. Also make this static so it doesn't 776 // get instantiated multiple times (causes a panic in statistics). 777 static CPUExecContext temp; 778 779 for (int i = 0; i < thread.size(); i++) { 780 nameOut(os, csprintf("%s.xc.%i", name(), i)); 781 temp.copyXC(thread[i]->getXCProxy()); 782 temp.serialize(os); 783 } 784} 785 786template <class Impl> 787void 788FullO3CPU<Impl>::unserialize(Checkpoint *cp, const std::string §ion) 789{ 790 BaseCPU::unserialize(cp, section); 791 tickEvent.unserialize(cp, csprintf("%s.tickEvent", section)); 792 793 // Use SimpleThread's ability to checkpoint to make it easier to 794 // read in the registers. Also make this static so it doesn't 795 // get instantiated multiple times (causes a panic in statistics). 796 static CPUExecContext temp; 797 798 for (int i = 0; i < thread.size(); i++) { 799 temp.copyXC(thread[i]->getXCProxy()); 800 temp.unserialize(cp, csprintf("%s.xc.%i", section, i)); 801 thread[i]->getXCProxy()->copyArchRegs(temp.getProxy()); 802 } 803} 804 805template <class Impl> 806uint64_t 807FullO3CPU<Impl>::readIntReg(int reg_idx) 808{ 809 return regFile.readIntReg(reg_idx); 810} 811 812template <class Impl> 813float 814FullO3CPU<Impl>::readFloatRegSingle(int reg_idx) 815{ 816 return regFile.readFloatRegSingle(reg_idx); 817} 818 819template <class Impl> 820double 821FullO3CPU<Impl>::readFloatRegDouble(int reg_idx) 822{ 823 return regFile.readFloatRegDouble(reg_idx); 824} 825 826template <class Impl> 827uint64_t 828FullO3CPU<Impl>::readFloatRegInt(int reg_idx) 829{ 830 return regFile.readFloatRegInt(reg_idx); 831} 832 833template <class Impl> 834void 835FullO3CPU<Impl>::setIntReg(int reg_idx, uint64_t val) 836{ 837 regFile.setIntReg(reg_idx, val); 838} 839 840template <class Impl> 841void 842FullO3CPU<Impl>::setFloatRegSingle(int reg_idx, float val) 843{ 844 regFile.setFloatRegSingle(reg_idx, val); 845} 846 847template <class Impl> 848void 849FullO3CPU<Impl>::setFloatRegDouble(int reg_idx, double val) 850{ 851 regFile.setFloatRegDouble(reg_idx, val); 852} 853 854template <class Impl> 855void 856FullO3CPU<Impl>::setFloatRegInt(int reg_idx, uint64_t val) 857{ 858 regFile.setFloatRegInt(reg_idx, val); 859} 860 861template <class Impl> 862uint64_t 863FullO3CPU<Impl>::readArchIntReg(int reg_idx, unsigned tid) 864{ 865 PhysRegIndex phys_reg = commitRenameMap[tid].lookup(reg_idx); 866 867 return regFile.readIntReg(phys_reg); 868} 869 870template <class Impl> 871float 872FullO3CPU<Impl>::readArchFloatRegSingle(int reg_idx, unsigned tid) 873{ 874 int idx = reg_idx + TheISA::FP_Base_DepTag; 875 PhysRegIndex phys_reg = commitRenameMap[tid].lookup(idx); 876 877 return regFile.readFloatRegSingle(phys_reg); 878} 879 880template <class Impl> 881double 882FullO3CPU<Impl>::readArchFloatRegDouble(int reg_idx, unsigned tid) 883{ 884 int idx = reg_idx + TheISA::FP_Base_DepTag; 885 PhysRegIndex phys_reg = commitRenameMap[tid].lookup(idx); 886 887 return regFile.readFloatRegDouble(phys_reg); 888} 889 890template <class Impl> 891uint64_t 892FullO3CPU<Impl>::readArchFloatRegInt(int reg_idx, unsigned tid) 893{ 894 int idx = reg_idx + TheISA::FP_Base_DepTag; 895 PhysRegIndex phys_reg = commitRenameMap[tid].lookup(idx); 896 897 return regFile.readFloatRegInt(phys_reg); 898} 899 900template <class Impl> 901void 902FullO3CPU<Impl>::setArchIntReg(int reg_idx, uint64_t val, unsigned tid) 903{ 904 PhysRegIndex phys_reg = commitRenameMap[tid].lookup(reg_idx); 905 906 regFile.setIntReg(phys_reg, val); 907} 908 909template <class Impl> 910void 911FullO3CPU<Impl>::setArchFloatRegSingle(int reg_idx, float val, unsigned tid) 912{ 913 int idx = reg_idx + TheISA::FP_Base_DepTag; 914 PhysRegIndex phys_reg = commitRenameMap[tid].lookup(idx); 915 916 regFile.setFloatRegSingle(phys_reg, val); 917} 918 919template <class Impl> 920void 921FullO3CPU<Impl>::setArchFloatRegDouble(int reg_idx, double val, unsigned tid) 922{ 923 int idx = reg_idx + TheISA::FP_Base_DepTag; 924 PhysRegIndex phys_reg = commitRenameMap[tid].lookup(idx); 925 926 regFile.setFloatRegDouble(phys_reg, val); 927} 928 929template <class Impl> 930void 931FullO3CPU<Impl>::setArchFloatRegInt(int reg_idx, uint64_t val, unsigned tid) 932{ 933 int idx = reg_idx + TheISA::FP_Base_DepTag; 934 PhysRegIndex phys_reg = commitRenameMap[tid].lookup(idx); 935 936 regFile.setFloatRegInt(phys_reg, val); 937} 938 939template <class Impl> 940uint64_t 941FullO3CPU<Impl>::readPC(unsigned tid) 942{ 943 return commit.readPC(tid); 944} 945 946template <class Impl> 947void 948FullO3CPU<Impl>::setPC(Addr new_PC,unsigned tid) 949{ 950 commit.setPC(new_PC, tid); 951} 952 953template <class Impl> 954uint64_t 955FullO3CPU<Impl>::readNextPC(unsigned tid) 956{ 957 return commit.readNextPC(tid); 958} 959 960template <class Impl> 961void 962FullO3CPU<Impl>::setNextPC(uint64_t val,unsigned tid) 963{ 964 commit.setNextPC(val, tid); 965} 966 967template <class Impl> 968typename FullO3CPU<Impl>::ListIt 969FullO3CPU<Impl>::addInst(DynInstPtr &inst) 970{ 971 instList.push_back(inst); 972 973 return --(instList.end()); 974} 975 976template <class Impl> 977void 978FullO3CPU<Impl>::instDone(unsigned tid) 979{ 980 // Keep an instruction count. 981 thread[tid]->numInst++; 982 thread[tid]->numInsts++; 983 committedInsts[tid]++; 984 totalCommittedInsts++; 985 986 // Check for instruction-count-based events. 987 comInstEventQueue[tid]->serviceEvents(thread[tid]->numInst); 988} 989 990template <class Impl> 991void 992FullO3CPU<Impl>::addToRemoveList(DynInstPtr &inst) 993{ 994 removeInstsThisCycle = true; 995 996 removeList.push(inst->getInstListIt()); 997} 998 999template <class Impl> 1000void 1001FullO3CPU<Impl>::removeFrontInst(DynInstPtr &inst) 1002{ 1003 DPRINTF(FullCPU, "FullCPU: Removing committed instruction [tid:%i] PC %#x " 1004 "[sn:%lli]\n", 1005 inst->threadNumber, inst->readPC(), inst->seqNum); 1006 1007 removeInstsThisCycle = true; 1008 1009 // Remove the front instruction. 1010 removeList.push(inst->getInstListIt()); 1011} 1012 1013template <class Impl> 1014void 1015FullO3CPU<Impl>::removeInstsNotInROB(unsigned tid) 1016{ 1017 DPRINTF(FullCPU, "FullCPU: Thread %i: Deleting instructions from instruction" 1018 " list.\n", tid); 1019 1020 ListIt end_it; 1021 1022 bool rob_empty = false; 1023 1024 if (instList.empty()) { 1025 return; 1026 } else if (rob.isEmpty(/*tid*/)) { 1027 DPRINTF(FullCPU, "FullCPU: ROB is empty, squashing all insts.\n"); 1028 end_it = instList.begin(); 1029 rob_empty = true; 1030 } else { 1031 end_it = (rob.readTailInst(tid))->getInstListIt(); 1032 DPRINTF(FullCPU, "FullCPU: ROB is not empty, squashing insts not in ROB.\n"); 1033 } 1034 1035 removeInstsThisCycle = true; 1036 1037 ListIt inst_it = instList.end(); 1038 1039 inst_it--; 1040 1041 // Walk through the instruction list, removing any instructions 1042 // that were inserted after the given instruction iterator, end_it. 1043 while (inst_it != end_it) { 1044 assert(!instList.empty()); 1045 1046 squashInstIt(inst_it, tid); 1047 1048 inst_it--; 1049 } 1050 1051 // If the ROB was empty, then we actually need to remove the first 1052 // instruction as well. 1053 if (rob_empty) { 1054 squashInstIt(inst_it, tid); 1055 } 1056} 1057 1058template <class Impl> 1059void 1060FullO3CPU<Impl>::removeInstsUntil(const InstSeqNum &seq_num, 1061 unsigned tid) 1062{ 1063 assert(!instList.empty()); 1064 1065 removeInstsThisCycle = true; 1066 1067 ListIt inst_iter = instList.end(); 1068 1069 inst_iter--; 1070 1071 DPRINTF(FullCPU, "FullCPU: Deleting instructions from instruction " 1072 "list that are from [tid:%i] and above [sn:%lli] (end=%lli).\n", 1073 tid, seq_num, (*inst_iter)->seqNum); 1074 1075 while ((*inst_iter)->seqNum > seq_num) { 1076 1077 bool break_loop = (inst_iter == instList.begin()); 1078 1079 squashInstIt(inst_iter, tid); 1080 1081 inst_iter--; 1082 1083 if (break_loop) 1084 break; 1085 } 1086} 1087 1088template <class Impl> 1089inline void 1090FullO3CPU<Impl>::squashInstIt(const ListIt &instIt, const unsigned &tid) 1091{ 1092 if ((*instIt)->threadNumber == tid) { 1093 DPRINTF(FullCPU, "FullCPU: Squashing instruction, " 1094 "[tid:%i] [sn:%lli] PC %#x\n", 1095 (*instIt)->threadNumber, 1096 (*instIt)->seqNum, 1097 (*instIt)->readPC()); 1098 1099 // Mark it as squashed. 1100 (*instIt)->setSquashed(); 1101 1102 // @todo: Formulate a consistent method for deleting 1103 // instructions from the instruction list 1104 // Remove the instruction from the list. 1105 removeList.push(instIt); 1106 } 1107} 1108 1109template <class Impl> 1110void 1111FullO3CPU<Impl>::cleanUpRemovedInsts() 1112{ 1113 while (!removeList.empty()) { 1114 DPRINTF(FullCPU, "FullCPU: Removing instruction, " 1115 "[tid:%i] [sn:%lli] PC %#x\n", 1116 (*removeList.front())->threadNumber, 1117 (*removeList.front())->seqNum, 1118 (*removeList.front())->readPC()); 1119 1120 instList.erase(removeList.front()); 1121 1122 removeList.pop(); 1123 } 1124 1125 removeInstsThisCycle = false; 1126} 1127/* 1128template <class Impl> 1129void 1130FullO3CPU<Impl>::removeAllInsts() 1131{ 1132 instList.clear(); 1133} 1134*/ 1135template <class Impl> 1136void 1137FullO3CPU<Impl>::dumpInsts() 1138{ 1139 int num = 0; 1140 1141 ListIt inst_list_it = instList.begin(); 1142 1143 cprintf("Dumping Instruction List\n"); 1144 1145 while (inst_list_it != instList.end()) { 1146 cprintf("Instruction:%i\nPC:%#x\n[tid:%i]\n[sn:%lli]\nIssued:%i\n" 1147 "Squashed:%i\n\n", 1148 num, (*inst_list_it)->readPC(), (*inst_list_it)->threadNumber, 1149 (*inst_list_it)->seqNum, (*inst_list_it)->isIssued(), 1150 (*inst_list_it)->isSquashed()); 1151 inst_list_it++; 1152 ++num; 1153 } 1154} 1155/* 1156template <class Impl> 1157void 1158FullO3CPU<Impl>::wakeDependents(DynInstPtr &inst) 1159{ 1160 iew.wakeDependents(inst); 1161} 1162*/ 1163template <class Impl> 1164void 1165FullO3CPU<Impl>::wakeCPU() 1166{ 1167 if (activityRec.active() || tickEvent.scheduled()) { 1168 DPRINTF(Activity, "CPU already running.\n"); 1169 return; 1170 } 1171 1172 DPRINTF(Activity, "Waking up CPU\n"); 1173 1174 idleCycles += (curTick - 1) - lastRunningCycle; 1175 1176 tickEvent.schedule(curTick); 1177} 1178 1179template <class Impl> 1180int 1181FullO3CPU<Impl>::getFreeTid() 1182{ 1183 for (int i=0; i < numThreads; i++) { 1184 if (!tids[i]) { 1185 tids[i] = true; 1186 return i; 1187 } 1188 } 1189 1190 return -1; 1191} 1192 1193template <class Impl> 1194void 1195FullO3CPU<Impl>::doContextSwitch() 1196{ 1197 if (contextSwitch) { 1198 1199 //ADD CODE TO DEACTIVE THREAD HERE (???) 1200 1201 for (int tid=0; tid < cpuWaitList.size(); tid++) { 1202 activateWhenReady(tid); 1203 } 1204 1205 if (cpuWaitList.size() == 0) 1206 contextSwitch = true; 1207 } 1208} 1209 1210template <class Impl> 1211void 1212FullO3CPU<Impl>::updateThreadPriority() 1213{ 1214 if (activeThreads.size() > 1) 1215 { 1216 //DEFAULT TO ROUND ROBIN SCHEME 1217 //e.g. Move highest priority to end of thread list 1218 list<unsigned>::iterator list_begin = activeThreads.begin(); 1219 list<unsigned>::iterator list_end = activeThreads.end(); 1220 1221 unsigned high_thread = *list_begin; 1222 1223 activeThreads.erase(list_begin); 1224 1225 activeThreads.push_back(high_thread); 1226 } 1227} 1228 1229// Forward declaration of FullO3CPU. 1230template class FullO3CPU<AlphaSimpleImpl>; 1231