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