fetch_impl.hh revision 2756:7bf0d6481df9
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 "arch/isa_traits.hh" 33#include "arch/utility.hh" 34#include "cpu/checker/cpu.hh" 35#include "cpu/exetrace.hh" 36#include "cpu/o3/fetch.hh" 37#include "mem/packet.hh" 38#include "mem/request.hh" 39#include "sim/byteswap.hh" 40#include "sim/host.hh" 41#include "sim/root.hh" 42 43#if FULL_SYSTEM 44#include "arch/tlb.hh" 45#include "arch/vtophys.hh" 46#include "base/remote_gdb.hh" 47#include "sim/system.hh" 48#endif // FULL_SYSTEM 49 50#include <algorithm> 51 52using namespace std; 53using namespace TheISA; 54 55template<class Impl> 56Tick 57DefaultFetch<Impl>::IcachePort::recvAtomic(PacketPtr pkt) 58{ 59 panic("DefaultFetch doesn't expect recvAtomic callback!"); 60 return curTick; 61} 62 63template<class Impl> 64void 65DefaultFetch<Impl>::IcachePort::recvFunctional(PacketPtr pkt) 66{ 67 panic("DefaultFetch doesn't expect recvFunctional callback!"); 68} 69 70template<class Impl> 71void 72DefaultFetch<Impl>::IcachePort::recvStatusChange(Status status) 73{ 74 if (status == RangeChange) 75 return; 76 77 panic("DefaultFetch doesn't expect recvStatusChange callback!"); 78} 79 80template<class Impl> 81bool 82DefaultFetch<Impl>::IcachePort::recvTiming(Packet *pkt) 83{ 84 fetch->processCacheCompletion(pkt); 85 return true; 86} 87 88template<class Impl> 89void 90DefaultFetch<Impl>::IcachePort::recvRetry() 91{ 92 fetch->recvRetry(); 93} 94 95template<class Impl> 96DefaultFetch<Impl>::DefaultFetch(Params *params) 97 : mem(params->mem), 98 branchPred(params), 99 decodeToFetchDelay(params->decodeToFetchDelay), 100 renameToFetchDelay(params->renameToFetchDelay), 101 iewToFetchDelay(params->iewToFetchDelay), 102 commitToFetchDelay(params->commitToFetchDelay), 103 fetchWidth(params->fetchWidth), 104 cacheBlocked(false), 105 retryPkt(NULL), 106 retryTid(-1), 107 numThreads(params->numberOfThreads), 108 numFetchingThreads(params->smtNumFetchingThreads), 109 interruptPending(false), 110 switchedOut(false) 111{ 112 if (numThreads > Impl::MaxThreads) 113 fatal("numThreads is not a valid value\n"); 114 115 DPRINTF(Fetch, "Fetch constructor called\n"); 116 117 // Set fetch stage's status to inactive. 118 _status = Inactive; 119 120 string policy = params->smtFetchPolicy; 121 122 // Convert string to lowercase 123 std::transform(policy.begin(), policy.end(), policy.begin(), 124 (int(*)(int)) tolower); 125 126 // Figure out fetch policy 127 if (policy == "singlethread") { 128 fetchPolicy = SingleThread; 129 } else if (policy == "roundrobin") { 130 fetchPolicy = RoundRobin; 131 DPRINTF(Fetch, "Fetch policy set to Round Robin\n"); 132 } else if (policy == "branch") { 133 fetchPolicy = Branch; 134 DPRINTF(Fetch, "Fetch policy set to Branch Count\n"); 135 } else if (policy == "iqcount") { 136 fetchPolicy = IQ; 137 DPRINTF(Fetch, "Fetch policy set to IQ count\n"); 138 } else if (policy == "lsqcount") { 139 fetchPolicy = LSQ; 140 DPRINTF(Fetch, "Fetch policy set to LSQ count\n"); 141 } else { 142 fatal("Invalid Fetch Policy. Options Are: {SingleThread," 143 " RoundRobin,LSQcount,IQcount}\n"); 144 } 145 146 // Size of cache block. 147 cacheBlkSize = 64; 148 149 // Create mask to get rid of offset bits. 150 cacheBlkMask = (cacheBlkSize - 1); 151 152 for (int tid=0; tid < numThreads; tid++) { 153 154 fetchStatus[tid] = Running; 155 156 priorityList.push_back(tid); 157 158 memReq[tid] = NULL; 159 160 // Create space to store a cache line. 161 cacheData[tid] = new uint8_t[cacheBlkSize]; 162 163 stalls[tid].decode = 0; 164 stalls[tid].rename = 0; 165 stalls[tid].iew = 0; 166 stalls[tid].commit = 0; 167 } 168 169 // Get the size of an instruction. 170 instSize = sizeof(MachInst); 171} 172 173template <class Impl> 174std::string 175DefaultFetch<Impl>::name() const 176{ 177 return cpu->name() + ".fetch"; 178} 179 180template <class Impl> 181void 182DefaultFetch<Impl>::regStats() 183{ 184 icacheStallCycles 185 .name(name() + ".icacheStallCycles") 186 .desc("Number of cycles fetch is stalled on an Icache miss") 187 .prereq(icacheStallCycles); 188 189 fetchedInsts 190 .name(name() + ".Insts") 191 .desc("Number of instructions fetch has processed") 192 .prereq(fetchedInsts); 193 194 fetchedBranches 195 .name(name() + ".Branches") 196 .desc("Number of branches that fetch encountered") 197 .prereq(fetchedBranches); 198 199 predictedBranches 200 .name(name() + ".predictedBranches") 201 .desc("Number of branches that fetch has predicted taken") 202 .prereq(predictedBranches); 203 204 fetchCycles 205 .name(name() + ".Cycles") 206 .desc("Number of cycles fetch has run and was not squashing or" 207 " blocked") 208 .prereq(fetchCycles); 209 210 fetchSquashCycles 211 .name(name() + ".SquashCycles") 212 .desc("Number of cycles fetch has spent squashing") 213 .prereq(fetchSquashCycles); 214 215 fetchIdleCycles 216 .name(name() + ".IdleCycles") 217 .desc("Number of cycles fetch was idle") 218 .prereq(fetchIdleCycles); 219 220 fetchBlockedCycles 221 .name(name() + ".BlockedCycles") 222 .desc("Number of cycles fetch has spent blocked") 223 .prereq(fetchBlockedCycles); 224 225 fetchedCacheLines 226 .name(name() + ".CacheLines") 227 .desc("Number of cache lines fetched") 228 .prereq(fetchedCacheLines); 229 230 fetchMiscStallCycles 231 .name(name() + ".MiscStallCycles") 232 .desc("Number of cycles fetch has spent waiting on interrupts, or " 233 "bad addresses, or out of MSHRs") 234 .prereq(fetchMiscStallCycles); 235 236 fetchIcacheSquashes 237 .name(name() + ".IcacheSquashes") 238 .desc("Number of outstanding Icache misses that were squashed") 239 .prereq(fetchIcacheSquashes); 240 241 fetchNisnDist 242 .init(/* base value */ 0, 243 /* last value */ fetchWidth, 244 /* bucket size */ 1) 245 .name(name() + ".rateDist") 246 .desc("Number of instructions fetched each cycle (Total)") 247 .flags(Stats::pdf); 248 249 idleRate 250 .name(name() + ".idleRate") 251 .desc("Percent of cycles fetch was idle") 252 .prereq(idleRate); 253 idleRate = fetchIdleCycles * 100 / cpu->numCycles; 254 255 branchRate 256 .name(name() + ".branchRate") 257 .desc("Number of branch fetches per cycle") 258 .flags(Stats::total); 259 branchRate = fetchedBranches / cpu->numCycles; 260 261 fetchRate 262 .name(name() + ".rate") 263 .desc("Number of inst fetches per cycle") 264 .flags(Stats::total); 265 fetchRate = fetchedInsts / cpu->numCycles; 266 267 branchPred.regStats(); 268} 269 270template<class Impl> 271void 272DefaultFetch<Impl>::setCPU(FullCPU *cpu_ptr) 273{ 274 DPRINTF(Fetch, "Setting the CPU pointer.\n"); 275 cpu = cpu_ptr; 276 277 // Name is finally available, so create the port. 278 icachePort = new IcachePort(this); 279 280 Port *mem_dport = mem->getPort(""); 281 icachePort->setPeer(mem_dport); 282 mem_dport->setPeer(icachePort); 283 284 if (cpu->checker) { 285 cpu->checker->setIcachePort(icachePort); 286 } 287 288 // Fetch needs to start fetching instructions at the very beginning, 289 // so it must start up in active state. 290 switchToActive(); 291} 292 293template<class Impl> 294void 295DefaultFetch<Impl>::setTimeBuffer(TimeBuffer<TimeStruct> *time_buffer) 296{ 297 DPRINTF(Fetch, "Setting the time buffer pointer.\n"); 298 timeBuffer = time_buffer; 299 300 // Create wires to get information from proper places in time buffer. 301 fromDecode = timeBuffer->getWire(-decodeToFetchDelay); 302 fromRename = timeBuffer->getWire(-renameToFetchDelay); 303 fromIEW = timeBuffer->getWire(-iewToFetchDelay); 304 fromCommit = timeBuffer->getWire(-commitToFetchDelay); 305} 306 307template<class Impl> 308void 309DefaultFetch<Impl>::setActiveThreads(list<unsigned> *at_ptr) 310{ 311 DPRINTF(Fetch, "Setting active threads list pointer.\n"); 312 activeThreads = at_ptr; 313} 314 315template<class Impl> 316void 317DefaultFetch<Impl>::setFetchQueue(TimeBuffer<FetchStruct> *fq_ptr) 318{ 319 DPRINTF(Fetch, "Setting the fetch queue pointer.\n"); 320 fetchQueue = fq_ptr; 321 322 // Create wire to write information to proper place in fetch queue. 323 toDecode = fetchQueue->getWire(0); 324} 325 326template<class Impl> 327void 328DefaultFetch<Impl>::initStage() 329{ 330 // Setup PC and nextPC with initial state. 331 for (int tid = 0; tid < numThreads; tid++) { 332 PC[tid] = cpu->readPC(tid); 333 nextPC[tid] = cpu->readNextPC(tid); 334#if THE_ISA != ALPHA_ISA 335 nextNPC[tid] = cpu->readNextNPC(tid); 336#endif 337 } 338} 339 340template<class Impl> 341void 342DefaultFetch<Impl>::processCacheCompletion(PacketPtr pkt) 343{ 344 unsigned tid = pkt->req->getThreadNum(); 345 346 DPRINTF(Fetch, "[tid:%u] Waking up from cache miss.\n",tid); 347 348 // Only change the status if it's still waiting on the icache access 349 // to return. 350 if (fetchStatus[tid] != IcacheWaitResponse || 351 pkt->req != memReq[tid] || 352 isSwitchedOut()) { 353 ++fetchIcacheSquashes; 354 delete pkt->req; 355 delete pkt; 356 memReq[tid] = NULL; 357 return; 358 } 359 360 // Wake up the CPU (if it went to sleep and was waiting on this completion 361 // event). 362 cpu->wakeCPU(); 363 364 DPRINTF(Activity, "[tid:%u] Activating fetch due to cache completion\n", 365 tid); 366 367 switchToActive(); 368 369 // Only switch to IcacheAccessComplete if we're not stalled as well. 370 if (checkStall(tid)) { 371 fetchStatus[tid] = Blocked; 372 } else { 373 fetchStatus[tid] = IcacheAccessComplete; 374 } 375 376 // Reset the mem req to NULL. 377 delete pkt->req; 378 delete pkt; 379 memReq[tid] = NULL; 380} 381 382template <class Impl> 383void 384DefaultFetch<Impl>::switchOut() 385{ 386 // Fetch is ready to switch out at any time. 387 switchedOut = true; 388 cpu->signalSwitched(); 389} 390 391template <class Impl> 392void 393DefaultFetch<Impl>::doSwitchOut() 394{ 395 // Branch predictor needs to have its state cleared. 396 branchPred.switchOut(); 397} 398 399template <class Impl> 400void 401DefaultFetch<Impl>::takeOverFrom() 402{ 403 // Reset all state 404 for (int i = 0; i < Impl::MaxThreads; ++i) { 405 stalls[i].decode = 0; 406 stalls[i].rename = 0; 407 stalls[i].iew = 0; 408 stalls[i].commit = 0; 409 PC[i] = cpu->readPC(i); 410 nextPC[i] = cpu->readNextPC(i); 411#if THE_ISA != ALPHA_ISA 412 nextNPC[i] = cpu->readNextNPC(i); 413#endif 414 fetchStatus[i] = Running; 415 } 416 numInst = 0; 417 wroteToTimeBuffer = false; 418 _status = Inactive; 419 switchedOut = false; 420 branchPred.takeOverFrom(); 421} 422 423template <class Impl> 424void 425DefaultFetch<Impl>::wakeFromQuiesce() 426{ 427 DPRINTF(Fetch, "Waking up from quiesce\n"); 428 // Hopefully this is safe 429 // @todo: Allow other threads to wake from quiesce. 430 fetchStatus[0] = Running; 431} 432 433template <class Impl> 434inline void 435DefaultFetch<Impl>::switchToActive() 436{ 437 if (_status == Inactive) { 438 DPRINTF(Activity, "Activating stage.\n"); 439 440 cpu->activateStage(FullCPU::FetchIdx); 441 442 _status = Active; 443 } 444} 445 446template <class Impl> 447inline void 448DefaultFetch<Impl>::switchToInactive() 449{ 450 if (_status == Active) { 451 DPRINTF(Activity, "Deactivating stage.\n"); 452 453 cpu->deactivateStage(FullCPU::FetchIdx); 454 455 _status = Inactive; 456 } 457} 458 459template <class Impl> 460bool 461DefaultFetch<Impl>::lookupAndUpdateNextPC(DynInstPtr &inst, Addr &next_PC) 462{ 463 // Do branch prediction check here. 464 // A bit of a misnomer...next_PC is actually the current PC until 465 // this function updates it. 466 bool predict_taken; 467 468 if (!inst->isControl()) { 469 next_PC = next_PC + instSize; 470 inst->setPredTarg(next_PC); 471 return false; 472 } 473 474 predict_taken = branchPred.predict(inst, next_PC, inst->threadNumber); 475 476 ++fetchedBranches; 477 478 if (predict_taken) { 479 ++predictedBranches; 480 } 481 482 return predict_taken; 483} 484 485template <class Impl> 486bool 487DefaultFetch<Impl>::fetchCacheLine(Addr fetch_PC, Fault &ret_fault, unsigned tid) 488{ 489 Fault fault = NoFault; 490 491#if FULL_SYSTEM 492 // Flag to say whether or not address is physical addr. 493 unsigned flags = cpu->inPalMode(fetch_PC) ? PHYSICAL : 0; 494#else 495 unsigned flags = 0; 496#endif // FULL_SYSTEM 497 498 if (cacheBlocked || (interruptPending && flags == 0) || switchedOut) { 499 // Hold off fetch from getting new instructions when: 500 // Cache is blocked, or 501 // while an interrupt is pending and we're not in PAL mode, or 502 // fetch is switched out. 503 return false; 504 } 505 506 // Align the fetch PC so it's at the start of a cache block. 507 fetch_PC = icacheBlockAlignPC(fetch_PC); 508 509 // Setup the memReq to do a read of the first instruction's address. 510 // Set the appropriate read size and flags as well. 511 // Build request here. 512 RequestPtr mem_req = new Request(tid, fetch_PC, cacheBlkSize, flags, 513 fetch_PC, cpu->readCpuId(), tid); 514 515 memReq[tid] = mem_req; 516 517 // Translate the instruction request. 518 fault = cpu->translateInstReq(mem_req, cpu->thread[tid]); 519 520 // In the case of faults, the fetch stage may need to stall and wait 521 // for the ITB miss to be handled. 522 523 // If translation was successful, attempt to read the first 524 // instruction. 525 if (fault == NoFault) { 526#if 0 527 if (cpu->system->memctrl->badaddr(memReq[tid]->paddr) || 528 memReq[tid]->flags & UNCACHEABLE) { 529 DPRINTF(Fetch, "Fetch: Bad address %#x (hopefully on a " 530 "misspeculating path)!", 531 memReq[tid]->paddr); 532 ret_fault = TheISA::genMachineCheckFault(); 533 return false; 534 } 535#endif 536 537 // Build packet here. 538 PacketPtr data_pkt = new Packet(mem_req, 539 Packet::ReadReq, Packet::Broadcast); 540 data_pkt->dataStatic(cacheData[tid]); 541 542 DPRINTF(Fetch, "Fetch: Doing instruction read.\n"); 543 544 fetchedCacheLines++; 545 546 // Now do the timing access to see whether or not the instruction 547 // exists within the cache. 548 if (!icachePort->sendTiming(data_pkt)) { 549 assert(retryPkt == NULL); 550 assert(retryTid == -1); 551 DPRINTF(Fetch, "[tid:%i] Out of MSHRs!\n", tid); 552 fetchStatus[tid] = IcacheWaitRetry; 553 retryPkt = data_pkt; 554 retryTid = tid; 555 cacheBlocked = true; 556 return false; 557 } 558 559 DPRINTF(Fetch, "Doing cache access.\n"); 560 561 lastIcacheStall[tid] = curTick; 562 563 DPRINTF(Activity, "[tid:%i]: Activity: Waiting on I-cache " 564 "response.\n", tid); 565 566 fetchStatus[tid] = IcacheWaitResponse; 567 } else { 568 delete mem_req; 569 memReq[tid] = NULL; 570 } 571 572 ret_fault = fault; 573 return true; 574} 575 576template <class Impl> 577inline void 578DefaultFetch<Impl>::doSquash(const Addr &new_PC, unsigned tid) 579{ 580 DPRINTF(Fetch, "[tid:%i]: Squashing, setting PC to: %#x.\n", 581 tid, new_PC); 582 583 PC[tid] = new_PC; 584 nextPC[tid] = new_PC + instSize; 585 586 // Clear the icache miss if it's outstanding. 587 if (fetchStatus[tid] == IcacheWaitResponse) { 588 DPRINTF(Fetch, "[tid:%i]: Squashing outstanding Icache miss.\n", 589 tid); 590 memReq[tid] = NULL; 591 } 592 593 // Get rid of the retrying packet if it was from this thread. 594 if (retryTid == tid) { 595 assert(cacheBlocked); 596 cacheBlocked = false; 597 retryTid = -1; 598 retryPkt = NULL; 599 delete retryPkt->req; 600 delete retryPkt; 601 } 602 603 fetchStatus[tid] = Squashing; 604 605 ++fetchSquashCycles; 606} 607 608template<class Impl> 609void 610DefaultFetch<Impl>::squashFromDecode(const Addr &new_PC, 611 const InstSeqNum &seq_num, 612 unsigned tid) 613{ 614 DPRINTF(Fetch, "[tid:%i]: Squashing from decode.\n",tid); 615 616 doSquash(new_PC, tid); 617 618 // Tell the CPU to remove any instructions that are in flight between 619 // fetch and decode. 620 cpu->removeInstsUntil(seq_num, tid); 621} 622 623template<class Impl> 624bool 625DefaultFetch<Impl>::checkStall(unsigned tid) const 626{ 627 bool ret_val = false; 628 629 if (cpu->contextSwitch) { 630 DPRINTF(Fetch,"[tid:%i]: Stalling for a context switch.\n",tid); 631 ret_val = true; 632 } else if (stalls[tid].decode) { 633 DPRINTF(Fetch,"[tid:%i]: Stall from Decode stage detected.\n",tid); 634 ret_val = true; 635 } else if (stalls[tid].rename) { 636 DPRINTF(Fetch,"[tid:%i]: Stall from Rename stage detected.\n",tid); 637 ret_val = true; 638 } else if (stalls[tid].iew) { 639 DPRINTF(Fetch,"[tid:%i]: Stall from IEW stage detected.\n",tid); 640 ret_val = true; 641 } else if (stalls[tid].commit) { 642 DPRINTF(Fetch,"[tid:%i]: Stall from Commit stage detected.\n",tid); 643 ret_val = true; 644 } 645 646 return ret_val; 647} 648 649template<class Impl> 650typename DefaultFetch<Impl>::FetchStatus 651DefaultFetch<Impl>::updateFetchStatus() 652{ 653 //Check Running 654 list<unsigned>::iterator threads = (*activeThreads).begin(); 655 656 while (threads != (*activeThreads).end()) { 657 658 unsigned tid = *threads++; 659 660 if (fetchStatus[tid] == Running || 661 fetchStatus[tid] == Squashing || 662 fetchStatus[tid] == IcacheAccessComplete) { 663 664 if (_status == Inactive) { 665 DPRINTF(Activity, "[tid:%i]: Activating stage.\n",tid); 666 667 if (fetchStatus[tid] == IcacheAccessComplete) { 668 DPRINTF(Activity, "[tid:%i]: Activating fetch due to cache" 669 "completion\n",tid); 670 } 671 672 cpu->activateStage(FullCPU::FetchIdx); 673 } 674 675 return Active; 676 } 677 } 678 679 // Stage is switching from active to inactive, notify CPU of it. 680 if (_status == Active) { 681 DPRINTF(Activity, "Deactivating stage.\n"); 682 683 cpu->deactivateStage(FullCPU::FetchIdx); 684 } 685 686 return Inactive; 687} 688 689template <class Impl> 690void 691DefaultFetch<Impl>::squash(const Addr &new_PC, unsigned tid) 692{ 693 DPRINTF(Fetch, "[tid:%u]: Squash from commit.\n",tid); 694 695 doSquash(new_PC, tid); 696 697 // Tell the CPU to remove any instructions that are not in the ROB. 698 cpu->removeInstsNotInROB(tid); 699} 700 701template <class Impl> 702void 703DefaultFetch<Impl>::tick() 704{ 705 list<unsigned>::iterator threads = (*activeThreads).begin(); 706 bool status_change = false; 707 708 wroteToTimeBuffer = false; 709 710 while (threads != (*activeThreads).end()) { 711 unsigned tid = *threads++; 712 713 // Check the signals for each thread to determine the proper status 714 // for each thread. 715 bool updated_status = checkSignalsAndUpdate(tid); 716 status_change = status_change || updated_status; 717 } 718 719 DPRINTF(Fetch, "Running stage.\n"); 720 721 // Reset the number of the instruction we're fetching. 722 numInst = 0; 723 724 if (fromCommit->commitInfo[0].interruptPending) { 725 interruptPending = true; 726 } 727 if (fromCommit->commitInfo[0].clearInterrupt) { 728 interruptPending = false; 729 } 730 731 for (threadFetched = 0; threadFetched < numFetchingThreads; 732 threadFetched++) { 733 // Fetch each of the actively fetching threads. 734 fetch(status_change); 735 } 736 737 // Record number of instructions fetched this cycle for distribution. 738 fetchNisnDist.sample(numInst); 739 740 if (status_change) { 741 // Change the fetch stage status if there was a status change. 742 _status = updateFetchStatus(); 743 } 744 745 // If there was activity this cycle, inform the CPU of it. 746 if (wroteToTimeBuffer || cpu->contextSwitch) { 747 DPRINTF(Activity, "Activity this cycle.\n"); 748 749 cpu->activityThisCycle(); 750 } 751} 752 753template <class Impl> 754bool 755DefaultFetch<Impl>::checkSignalsAndUpdate(unsigned tid) 756{ 757 // Update the per thread stall statuses. 758 if (fromDecode->decodeBlock[tid]) { 759 stalls[tid].decode = true; 760 } 761 762 if (fromDecode->decodeUnblock[tid]) { 763 assert(stalls[tid].decode); 764 assert(!fromDecode->decodeBlock[tid]); 765 stalls[tid].decode = false; 766 } 767 768 if (fromRename->renameBlock[tid]) { 769 stalls[tid].rename = true; 770 } 771 772 if (fromRename->renameUnblock[tid]) { 773 assert(stalls[tid].rename); 774 assert(!fromRename->renameBlock[tid]); 775 stalls[tid].rename = false; 776 } 777 778 if (fromIEW->iewBlock[tid]) { 779 stalls[tid].iew = true; 780 } 781 782 if (fromIEW->iewUnblock[tid]) { 783 assert(stalls[tid].iew); 784 assert(!fromIEW->iewBlock[tid]); 785 stalls[tid].iew = false; 786 } 787 788 if (fromCommit->commitBlock[tid]) { 789 stalls[tid].commit = true; 790 } 791 792 if (fromCommit->commitUnblock[tid]) { 793 assert(stalls[tid].commit); 794 assert(!fromCommit->commitBlock[tid]); 795 stalls[tid].commit = false; 796 } 797 798 // Check squash signals from commit. 799 if (fromCommit->commitInfo[tid].squash) { 800 801 DPRINTF(Fetch, "[tid:%u]: Squashing instructions due to squash " 802 "from commit.\n",tid); 803 804 // In any case, squash. 805 squash(fromCommit->commitInfo[tid].nextPC,tid); 806 807 // Also check if there's a mispredict that happened. 808 if (fromCommit->commitInfo[tid].branchMispredict) { 809 branchPred.squash(fromCommit->commitInfo[tid].doneSeqNum, 810 fromCommit->commitInfo[tid].nextPC, 811 fromCommit->commitInfo[tid].branchTaken, 812 tid); 813 } else { 814 branchPred.squash(fromCommit->commitInfo[tid].doneSeqNum, 815 tid); 816 } 817 818 return true; 819 } else if (fromCommit->commitInfo[tid].doneSeqNum) { 820 // Update the branch predictor if it wasn't a squashed instruction 821 // that was broadcasted. 822 branchPred.update(fromCommit->commitInfo[tid].doneSeqNum, tid); 823 } 824 825 // Check ROB squash signals from commit. 826 if (fromCommit->commitInfo[tid].robSquashing) { 827 DPRINTF(Fetch, "[tid:%u]: ROB is still squashing.\n", tid); 828 829 // Continue to squash. 830 fetchStatus[tid] = Squashing; 831 832 return true; 833 } 834 835 // Check squash signals from decode. 836 if (fromDecode->decodeInfo[tid].squash) { 837 DPRINTF(Fetch, "[tid:%u]: Squashing instructions due to squash " 838 "from decode.\n",tid); 839 840 // Update the branch predictor. 841 if (fromDecode->decodeInfo[tid].branchMispredict) { 842 branchPred.squash(fromDecode->decodeInfo[tid].doneSeqNum, 843 fromDecode->decodeInfo[tid].nextPC, 844 fromDecode->decodeInfo[tid].branchTaken, 845 tid); 846 } else { 847 branchPred.squash(fromDecode->decodeInfo[tid].doneSeqNum, 848 tid); 849 } 850 851 if (fetchStatus[tid] != Squashing) { 852 // Squash unless we're already squashing 853 squashFromDecode(fromDecode->decodeInfo[tid].nextPC, 854 fromDecode->decodeInfo[tid].doneSeqNum, 855 tid); 856 857 return true; 858 } 859 } 860 861 if (checkStall(tid) && fetchStatus[tid] != IcacheWaitResponse) { 862 DPRINTF(Fetch, "[tid:%i]: Setting to blocked\n",tid); 863 864 fetchStatus[tid] = Blocked; 865 866 return true; 867 } 868 869 if (fetchStatus[tid] == Blocked || 870 fetchStatus[tid] == Squashing) { 871 // Switch status to running if fetch isn't being told to block or 872 // squash this cycle. 873 DPRINTF(Fetch, "[tid:%i]: Done squashing, switching to running.\n", 874 tid); 875 876 fetchStatus[tid] = Running; 877 878 return true; 879 } 880 881 // If we've reached this point, we have not gotten any signals that 882 // cause fetch to change its status. Fetch remains the same as before. 883 return false; 884} 885 886template<class Impl> 887void 888DefaultFetch<Impl>::fetch(bool &status_change) 889{ 890 ////////////////////////////////////////// 891 // Start actual fetch 892 ////////////////////////////////////////// 893 int tid = getFetchingThread(fetchPolicy); 894 895 if (tid == -1) { 896 DPRINTF(Fetch,"There are no more threads available to fetch from.\n"); 897 898 // Breaks looping condition in tick() 899 threadFetched = numFetchingThreads; 900 return; 901 } 902 903 // The current PC. 904 Addr &fetch_PC = PC[tid]; 905 906 // Fault code for memory access. 907 Fault fault = NoFault; 908 909 // If returning from the delay of a cache miss, then update the status 910 // to running, otherwise do the cache access. Possibly move this up 911 // to tick() function. 912 if (fetchStatus[tid] == IcacheAccessComplete) { 913 DPRINTF(Fetch, "[tid:%i]: Icache miss is complete.\n", 914 tid); 915 916 fetchStatus[tid] = Running; 917 status_change = true; 918 } else if (fetchStatus[tid] == Running) { 919 DPRINTF(Fetch, "[tid:%i]: Attempting to translate and read " 920 "instruction, starting at PC %08p.\n", 921 tid, fetch_PC); 922 923 bool fetch_success = fetchCacheLine(fetch_PC, fault, tid); 924 if (!fetch_success) { 925 if (cacheBlocked) { 926 ++icacheStallCycles; 927 } else { 928 ++fetchMiscStallCycles; 929 } 930 return; 931 } 932 } else { 933 if (fetchStatus[tid] == Idle) { 934 ++fetchIdleCycles; 935 } else if (fetchStatus[tid] == Blocked) { 936 ++fetchBlockedCycles; 937 } else if (fetchStatus[tid] == Squashing) { 938 ++fetchSquashCycles; 939 } else if (fetchStatus[tid] == IcacheWaitResponse) { 940 ++icacheStallCycles; 941 } 942 943 // Status is Idle, Squashing, Blocked, or IcacheWaitResponse, so 944 // fetch should do nothing. 945 return; 946 } 947 948 ++fetchCycles; 949 950 // If we had a stall due to an icache miss, then return. 951 if (fetchStatus[tid] == IcacheWaitResponse) { 952 ++icacheStallCycles; 953 status_change = true; 954 return; 955 } 956 957 Addr next_PC = fetch_PC; 958 InstSeqNum inst_seq; 959 MachInst inst; 960 ExtMachInst ext_inst; 961 // @todo: Fix this hack. 962 unsigned offset = (fetch_PC & cacheBlkMask) & ~3; 963 964 if (fault == NoFault) { 965 // If the read of the first instruction was successful, then grab the 966 // instructions from the rest of the cache line and put them into the 967 // queue heading to decode. 968 969 DPRINTF(Fetch, "[tid:%i]: Adding instructions to queue to " 970 "decode.\n",tid); 971 972 // Need to keep track of whether or not a predicted branch 973 // ended this fetch block. 974 bool predicted_branch = false; 975 976 for (; 977 offset < cacheBlkSize && 978 numInst < fetchWidth && 979 !predicted_branch; 980 ++numInst) { 981 982 // Get a sequence number. 983 inst_seq = cpu->getAndIncrementInstSeq(); 984 985 // Make sure this is a valid index. 986 assert(offset <= cacheBlkSize - instSize); 987 988 // Get the instruction from the array of the cache line. 989 inst = gtoh(*reinterpret_cast<MachInst *> 990 (&cacheData[tid][offset])); 991 992 ext_inst = TheISA::makeExtMI(inst, fetch_PC); 993 994 // Create a new DynInst from the instruction fetched. 995 DynInstPtr instruction = new DynInst(ext_inst, fetch_PC, 996 next_PC, 997 inst_seq, cpu); 998 instruction->setTid(tid); 999 1000 instruction->setASID(tid); 1001 1002 instruction->setThreadState(cpu->thread[tid]); 1003 1004 DPRINTF(Fetch, "[tid:%i]: Instruction PC %#x created " 1005 "[sn:%lli]\n", 1006 tid, instruction->readPC(), inst_seq); 1007 1008 DPRINTF(Fetch, "[tid:%i]: Instruction is: %s\n", 1009 tid, instruction->staticInst->disassemble(fetch_PC)); 1010 1011 instruction->traceData = 1012 Trace::getInstRecord(curTick, cpu->tcBase(tid), cpu, 1013 instruction->staticInst, 1014 instruction->readPC(),tid); 1015 1016 predicted_branch = lookupAndUpdateNextPC(instruction, next_PC); 1017 1018 // Add instruction to the CPU's list of instructions. 1019 instruction->setInstListIt(cpu->addInst(instruction)); 1020 1021 // Write the instruction to the first slot in the queue 1022 // that heads to decode. 1023 toDecode->insts[numInst] = instruction; 1024 1025 toDecode->size++; 1026 1027 // Increment stat of fetched instructions. 1028 ++fetchedInsts; 1029 1030 // Move to the next instruction, unless we have a branch. 1031 fetch_PC = next_PC; 1032 1033 if (instruction->isQuiesce()) { 1034 warn("cycle %lli: Quiesce instruction encountered, halting fetch!", 1035 curTick); 1036 fetchStatus[tid] = QuiescePending; 1037 ++numInst; 1038 status_change = true; 1039 break; 1040 } 1041 1042 offset+= instSize; 1043 } 1044 } 1045 1046 if (numInst > 0) { 1047 wroteToTimeBuffer = true; 1048 } 1049 1050 // Now that fetching is completed, update the PC to signify what the next 1051 // cycle will be. 1052 if (fault == NoFault) { 1053 DPRINTF(Fetch, "[tid:%i]: Setting PC to %08p.\n",tid, next_PC); 1054 1055#if THE_ISA == ALPHA_ISA 1056 PC[tid] = next_PC; 1057 nextPC[tid] = next_PC + instSize; 1058#else 1059 PC[tid] = next_PC; 1060 nextPC[tid] = next_PC + instSize; 1061 nextPC[tid] = next_PC + instSize; 1062 1063 thread->setNextPC(thread->readNextNPC()); 1064 thread->setNextNPC(thread->readNextNPC() + sizeof(MachInst)); 1065#endif 1066 } else { 1067 // We shouldn't be in an icache miss and also have a fault (an ITB 1068 // miss) 1069 if (fetchStatus[tid] == IcacheWaitResponse) { 1070 panic("Fetch should have exited prior to this!"); 1071 } 1072 1073 // Send the fault to commit. This thread will not do anything 1074 // until commit handles the fault. The only other way it can 1075 // wake up is if a squash comes along and changes the PC. 1076#if FULL_SYSTEM 1077 assert(numInst != fetchWidth); 1078 // Get a sequence number. 1079 inst_seq = cpu->getAndIncrementInstSeq(); 1080 // We will use a nop in order to carry the fault. 1081 ext_inst = TheISA::NoopMachInst; 1082 1083 // Create a new DynInst from the dummy nop. 1084 DynInstPtr instruction = new DynInst(ext_inst, fetch_PC, 1085 next_PC, 1086 inst_seq, cpu); 1087 instruction->setPredTarg(next_PC + instSize); 1088 instruction->setTid(tid); 1089 1090 instruction->setASID(tid); 1091 1092 instruction->setThreadState(cpu->thread[tid]); 1093 1094 instruction->traceData = NULL; 1095 1096 instruction->setInstListIt(cpu->addInst(instruction)); 1097 1098 instruction->fault = fault; 1099 1100 toDecode->insts[numInst] = instruction; 1101 toDecode->size++; 1102 1103 DPRINTF(Fetch, "[tid:%i]: Blocked, need to handle the trap.\n",tid); 1104 1105 fetchStatus[tid] = TrapPending; 1106 status_change = true; 1107 1108 warn("cycle %lli: fault (%d) detected @ PC %08p", curTick, fault, PC[tid]); 1109#else // !FULL_SYSTEM 1110 warn("cycle %lli: fault (%d) detected @ PC %08p", curTick, fault, PC[tid]); 1111#endif // FULL_SYSTEM 1112 } 1113} 1114 1115template<class Impl> 1116void 1117DefaultFetch<Impl>::recvRetry() 1118{ 1119 assert(cacheBlocked); 1120 if (retryPkt != NULL) { 1121 assert(retryTid != -1); 1122 assert(fetchStatus[retryTid] == IcacheWaitRetry); 1123 1124 if (icachePort->sendTiming(retryPkt)) { 1125 fetchStatus[retryTid] = IcacheWaitResponse; 1126 retryPkt = NULL; 1127 retryTid = -1; 1128 cacheBlocked = false; 1129 } 1130 } else { 1131 assert(retryTid == -1); 1132 // Access has been squashed since it was sent out. Just clear 1133 // the cache being blocked. 1134 cacheBlocked = false; 1135 } 1136} 1137 1138/////////////////////////////////////// 1139// // 1140// SMT FETCH POLICY MAINTAINED HERE // 1141// // 1142/////////////////////////////////////// 1143template<class Impl> 1144int 1145DefaultFetch<Impl>::getFetchingThread(FetchPriority &fetch_priority) 1146{ 1147 if (numThreads > 1) { 1148 switch (fetch_priority) { 1149 1150 case SingleThread: 1151 return 0; 1152 1153 case RoundRobin: 1154 return roundRobin(); 1155 1156 case IQ: 1157 return iqCount(); 1158 1159 case LSQ: 1160 return lsqCount(); 1161 1162 case Branch: 1163 return branchCount(); 1164 1165 default: 1166 return -1; 1167 } 1168 } else { 1169 int tid = *((*activeThreads).begin()); 1170 1171 if (fetchStatus[tid] == Running || 1172 fetchStatus[tid] == IcacheAccessComplete || 1173 fetchStatus[tid] == Idle) { 1174 return tid; 1175 } else { 1176 return -1; 1177 } 1178 } 1179 1180} 1181 1182 1183template<class Impl> 1184int 1185DefaultFetch<Impl>::roundRobin() 1186{ 1187 list<unsigned>::iterator pri_iter = priorityList.begin(); 1188 list<unsigned>::iterator end = priorityList.end(); 1189 1190 int high_pri; 1191 1192 while (pri_iter != end) { 1193 high_pri = *pri_iter; 1194 1195 assert(high_pri <= numThreads); 1196 1197 if (fetchStatus[high_pri] == Running || 1198 fetchStatus[high_pri] == IcacheAccessComplete || 1199 fetchStatus[high_pri] == Idle) { 1200 1201 priorityList.erase(pri_iter); 1202 priorityList.push_back(high_pri); 1203 1204 return high_pri; 1205 } 1206 1207 pri_iter++; 1208 } 1209 1210 return -1; 1211} 1212 1213template<class Impl> 1214int 1215DefaultFetch<Impl>::iqCount() 1216{ 1217 priority_queue<unsigned> PQ; 1218 1219 list<unsigned>::iterator threads = (*activeThreads).begin(); 1220 1221 while (threads != (*activeThreads).end()) { 1222 unsigned tid = *threads++; 1223 1224 PQ.push(fromIEW->iewInfo[tid].iqCount); 1225 } 1226 1227 while (!PQ.empty()) { 1228 1229 unsigned high_pri = PQ.top(); 1230 1231 if (fetchStatus[high_pri] == Running || 1232 fetchStatus[high_pri] == IcacheAccessComplete || 1233 fetchStatus[high_pri] == Idle) 1234 return high_pri; 1235 else 1236 PQ.pop(); 1237 1238 } 1239 1240 return -1; 1241} 1242 1243template<class Impl> 1244int 1245DefaultFetch<Impl>::lsqCount() 1246{ 1247 priority_queue<unsigned> PQ; 1248 1249 1250 list<unsigned>::iterator threads = (*activeThreads).begin(); 1251 1252 while (threads != (*activeThreads).end()) { 1253 unsigned tid = *threads++; 1254 1255 PQ.push(fromIEW->iewInfo[tid].ldstqCount); 1256 } 1257 1258 while (!PQ.empty()) { 1259 1260 unsigned high_pri = PQ.top(); 1261 1262 if (fetchStatus[high_pri] == Running || 1263 fetchStatus[high_pri] == IcacheAccessComplete || 1264 fetchStatus[high_pri] == Idle) 1265 return high_pri; 1266 else 1267 PQ.pop(); 1268 1269 } 1270 1271 return -1; 1272} 1273 1274template<class Impl> 1275int 1276DefaultFetch<Impl>::branchCount() 1277{ 1278 list<unsigned>::iterator threads = (*activeThreads).begin(); 1279 warn("Branch Count Fetch policy unimplemented\n"); 1280 return *threads; 1281} 1282