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