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