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