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