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