fetch_impl.hh revision 8733:64a7bf8fa56c
1/* 2 * Copyright (c) 2010-2011 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#include <list> 47#include <map> 48#include <queue> 49 50#include "arch/isa_traits.hh" 51#include "arch/utility.hh" 52#include "base/types.hh" 53#include "config/the_isa.hh" 54#include "config/use_checker.hh" 55#include "cpu/base.hh" 56#include "cpu/o3/fetch.hh" 57#include "cpu/exetrace.hh" 58#include "debug/Activity.hh" 59#include "debug/Fetch.hh" 60#include "mem/packet.hh" 61#include "mem/request.hh" 62#include "params/DerivO3CPU.hh" 63#include "sim/byteswap.hh" 64#include "sim/core.hh" 65#include "sim/eventq.hh" 66 67#if FULL_SYSTEM 68#include "arch/tlb.hh" 69#include "arch/vtophys.hh" 70#include "sim/system.hh" 71#endif // FULL_SYSTEM 72 73#if USE_CHECKER 74#include "cpu/checker/cpu.hh" 75#endif // USE_CHECKER 76 77using namespace std; 78 79template<class Impl> 80DefaultFetch<Impl>::DefaultFetch(O3CPU *_cpu, DerivO3CPUParams *params) 81 : cpu(_cpu), 82 branchPred(params), 83 predecoder(NULL), 84 numInst(0), 85 decodeToFetchDelay(params->decodeToFetchDelay), 86 renameToFetchDelay(params->renameToFetchDelay), 87 iewToFetchDelay(params->iewToFetchDelay), 88 commitToFetchDelay(params->commitToFetchDelay), 89 fetchWidth(params->fetchWidth), 90 cacheBlocked(false), 91 retryPkt(NULL), 92 retryTid(InvalidThreadID), 93 numThreads(params->numThreads), 94 numFetchingThreads(params->smtNumFetchingThreads), 95 interruptPending(false), 96 drainPending(false), 97 switchedOut(false), 98 finishTranslationEvent(this) 99{ 100 if (numThreads > Impl::MaxThreads) 101 fatal("numThreads (%d) is larger than compiled limit (%d),\n" 102 "\tincrease MaxThreads in src/cpu/o3/impl.hh\n", 103 numThreads, static_cast<int>(Impl::MaxThreads)); 104 105 // Set fetch stage's status to inactive. 106 _status = Inactive; 107 108 std::string policy = params->smtFetchPolicy; 109 110 // Convert string to lowercase 111 std::transform(policy.begin(), policy.end(), policy.begin(), 112 (int(*)(int)) tolower); 113 114 // Figure out fetch policy 115 if (policy == "singlethread") { 116 fetchPolicy = SingleThread; 117 if (numThreads > 1) 118 panic("Invalid Fetch Policy for a SMT workload."); 119 } else if (policy == "roundrobin") { 120 fetchPolicy = RoundRobin; 121 DPRINTF(Fetch, "Fetch policy set to Round Robin\n"); 122 } else if (policy == "branch") { 123 fetchPolicy = Branch; 124 DPRINTF(Fetch, "Fetch policy set to Branch Count\n"); 125 } else if (policy == "iqcount") { 126 fetchPolicy = IQ; 127 DPRINTF(Fetch, "Fetch policy set to IQ count\n"); 128 } else if (policy == "lsqcount") { 129 fetchPolicy = LSQ; 130 DPRINTF(Fetch, "Fetch policy set to LSQ count\n"); 131 } else { 132 fatal("Invalid Fetch Policy. Options Are: {SingleThread," 133 " RoundRobin,LSQcount,IQcount}\n"); 134 } 135 136 // Get the size of an instruction. 137 instSize = sizeof(TheISA::MachInst); 138} 139 140template <class Impl> 141std::string 142DefaultFetch<Impl>::name() const 143{ 144 return cpu->name() + ".fetch"; 145} 146 147template <class Impl> 148void 149DefaultFetch<Impl>::regStats() 150{ 151 icacheStallCycles 152 .name(name() + ".icacheStallCycles") 153 .desc("Number of cycles fetch is stalled on an Icache miss") 154 .prereq(icacheStallCycles); 155 156 fetchedInsts 157 .name(name() + ".Insts") 158 .desc("Number of instructions fetch has processed") 159 .prereq(fetchedInsts); 160 161 fetchedBranches 162 .name(name() + ".Branches") 163 .desc("Number of branches that fetch encountered") 164 .prereq(fetchedBranches); 165 166 predictedBranches 167 .name(name() + ".predictedBranches") 168 .desc("Number of branches that fetch has predicted taken") 169 .prereq(predictedBranches); 170 171 fetchCycles 172 .name(name() + ".Cycles") 173 .desc("Number of cycles fetch has run and was not squashing or" 174 " blocked") 175 .prereq(fetchCycles); 176 177 fetchSquashCycles 178 .name(name() + ".SquashCycles") 179 .desc("Number of cycles fetch has spent squashing") 180 .prereq(fetchSquashCycles); 181 182 fetchTlbCycles 183 .name(name() + ".TlbCycles") 184 .desc("Number of cycles fetch has spent waiting for tlb") 185 .prereq(fetchTlbCycles); 186 187 fetchIdleCycles 188 .name(name() + ".IdleCycles") 189 .desc("Number of cycles fetch was idle") 190 .prereq(fetchIdleCycles); 191 192 fetchBlockedCycles 193 .name(name() + ".BlockedCycles") 194 .desc("Number of cycles fetch has spent blocked") 195 .prereq(fetchBlockedCycles); 196 197 fetchedCacheLines 198 .name(name() + ".CacheLines") 199 .desc("Number of cache lines fetched") 200 .prereq(fetchedCacheLines); 201 202 fetchMiscStallCycles 203 .name(name() + ".MiscStallCycles") 204 .desc("Number of cycles fetch has spent waiting on interrupts, or " 205 "bad addresses, or out of MSHRs") 206 .prereq(fetchMiscStallCycles); 207 208 fetchPendingDrainCycles 209 .name(name() + ".PendingDrainCycles") 210 .desc("Number of cycles fetch has spent waiting on pipes to drain") 211 .prereq(fetchPendingDrainCycles); 212 213 fetchNoActiveThreadStallCycles 214 .name(name() + ".NoActiveThreadStallCycles") 215 .desc("Number of stall cycles due to no active thread to fetch from") 216 .prereq(fetchNoActiveThreadStallCycles); 217 218 fetchPendingTrapStallCycles 219 .name(name() + ".PendingTrapStallCycles") 220 .desc("Number of stall cycles due to pending traps") 221 .prereq(fetchPendingTrapStallCycles); 222 223 fetchPendingQuiesceStallCycles 224 .name(name() + ".PendingQuiesceStallCycles") 225 .desc("Number of stall cycles due to pending quiesce instructions") 226 .prereq(fetchPendingQuiesceStallCycles); 227 228 fetchIcacheWaitRetryStallCycles 229 .name(name() + ".IcacheWaitRetryStallCycles") 230 .desc("Number of stall cycles due to full MSHR") 231 .prereq(fetchIcacheWaitRetryStallCycles); 232 233 fetchIcacheSquashes 234 .name(name() + ".IcacheSquashes") 235 .desc("Number of outstanding Icache misses that were squashed") 236 .prereq(fetchIcacheSquashes); 237 238 fetchTlbSquashes 239 .name(name() + ".ItlbSquashes") 240 .desc("Number of outstanding ITLB misses that were squashed") 241 .prereq(fetchTlbSquashes); 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>::setTimeBuffer(TimeBuffer<TimeStruct> *time_buffer) 275{ 276 timeBuffer = time_buffer; 277 278 // Create wires to get information from proper places in time buffer. 279 fromDecode = timeBuffer->getWire(-decodeToFetchDelay); 280 fromRename = timeBuffer->getWire(-renameToFetchDelay); 281 fromIEW = timeBuffer->getWire(-iewToFetchDelay); 282 fromCommit = timeBuffer->getWire(-commitToFetchDelay); 283} 284 285template<class Impl> 286void 287DefaultFetch<Impl>::setActiveThreads(std::list<ThreadID> *at_ptr) 288{ 289 activeThreads = at_ptr; 290} 291 292template<class Impl> 293void 294DefaultFetch<Impl>::setFetchQueue(TimeBuffer<FetchStruct> *fq_ptr) 295{ 296 fetchQueue = fq_ptr; 297 298 // Create wire to write information to proper place in fetch queue. 299 toDecode = fetchQueue->getWire(0); 300} 301 302template<class Impl> 303void 304DefaultFetch<Impl>::initStage() 305{ 306 // Setup PC and nextPC with initial state. 307 for (ThreadID tid = 0; tid < numThreads; tid++) { 308 pc[tid] = cpu->pcState(tid); 309 fetchOffset[tid] = 0; 310 macroop[tid] = NULL; 311 delayedCommit[tid] = false; 312 } 313 314 for (ThreadID tid = 0; tid < numThreads; tid++) { 315 316 fetchStatus[tid] = Running; 317 318 priorityList.push_back(tid); 319 320 memReq[tid] = NULL; 321 322 stalls[tid].decode = false; 323 stalls[tid].rename = false; 324 stalls[tid].iew = false; 325 stalls[tid].commit = false; 326 } 327 328 // Schedule fetch to get the correct PC from the CPU 329 // scheduleFetchStartupEvent(1); 330 331 // Fetch needs to start fetching instructions at the very beginning, 332 // so it must start up in active state. 333 switchToActive(); 334} 335 336template<class Impl> 337void 338DefaultFetch<Impl>::setIcache() 339{ 340 assert(cpu->getIcachePort()->isConnected()); 341 342 // Size of cache block. 343 cacheBlkSize = cpu->getIcachePort()->peerBlockSize(); 344 345 // Create mask to get rid of offset bits. 346 cacheBlkMask = (cacheBlkSize - 1); 347 348 for (ThreadID tid = 0; tid < numThreads; tid++) { 349 // Create space to store a cache line. 350 cacheData[tid] = new uint8_t[cacheBlkSize]; 351 cacheDataPC[tid] = 0; 352 cacheDataValid[tid] = false; 353 } 354} 355 356template<class Impl> 357void 358DefaultFetch<Impl>::processCacheCompletion(PacketPtr pkt) 359{ 360 ThreadID tid = pkt->req->threadId(); 361 362 DPRINTF(Fetch, "[tid:%u] Waking up from cache miss.\n", tid); 363 364 assert(!pkt->wasNacked()); 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 return; 375 } 376 377 memcpy(cacheData[tid], pkt->getPtr<uint8_t>(), cacheBlkSize); 378 cacheDataValid[tid] = true; 379 380 if (!drainPending) { 381 // Wake up the CPU (if it went to sleep and was waiting on 382 // this completion event). 383 cpu->wakeCPU(); 384 385 DPRINTF(Activity, "[tid:%u] Activating fetch due to cache completion\n", 386 tid); 387 388 switchToActive(); 389 } 390 391 // Only switch to IcacheAccessComplete if we're not stalled as well. 392 if (checkStall(tid)) { 393 fetchStatus[tid] = Blocked; 394 } else { 395 fetchStatus[tid] = IcacheAccessComplete; 396 } 397 398 // Reset the mem req to NULL. 399 delete pkt->req; 400 delete pkt; 401 memReq[tid] = NULL; 402} 403 404template <class Impl> 405bool 406DefaultFetch<Impl>::drain() 407{ 408 // Fetch is ready to drain at any time. 409 cpu->signalDrained(); 410 drainPending = true; 411 return true; 412} 413 414template <class Impl> 415void 416DefaultFetch<Impl>::resume() 417{ 418 drainPending = false; 419} 420 421template <class Impl> 422void 423DefaultFetch<Impl>::switchOut() 424{ 425 switchedOut = true; 426 // Branch predictor needs to have its state cleared. 427 branchPred.switchOut(); 428} 429 430template <class Impl> 431void 432DefaultFetch<Impl>::takeOverFrom() 433{ 434 // the instruction port is now connected so we can get the block 435 // size 436 setIcache(); 437 438 // Reset all state 439 for (ThreadID i = 0; i < Impl::MaxThreads; ++i) { 440 stalls[i].decode = 0; 441 stalls[i].rename = 0; 442 stalls[i].iew = 0; 443 stalls[i].commit = 0; 444 pc[i] = cpu->pcState(i); 445 fetchStatus[i] = Running; 446 } 447 numInst = 0; 448 wroteToTimeBuffer = false; 449 _status = Inactive; 450 switchedOut = false; 451 interruptPending = false; 452 branchPred.takeOverFrom(); 453} 454 455template <class Impl> 456void 457DefaultFetch<Impl>::wakeFromQuiesce() 458{ 459 DPRINTF(Fetch, "Waking up from quiesce\n"); 460 // Hopefully this is safe 461 // @todo: Allow other threads to wake from quiesce. 462 fetchStatus[0] = Running; 463} 464 465template <class Impl> 466inline void 467DefaultFetch<Impl>::switchToActive() 468{ 469 if (_status == Inactive) { 470 DPRINTF(Activity, "Activating stage.\n"); 471 472 cpu->activateStage(O3CPU::FetchIdx); 473 474 _status = Active; 475 } 476} 477 478template <class Impl> 479inline void 480DefaultFetch<Impl>::switchToInactive() 481{ 482 if (_status == Active) { 483 DPRINTF(Activity, "Deactivating stage.\n"); 484 485 cpu->deactivateStage(O3CPU::FetchIdx); 486 487 _status = Inactive; 488 } 489} 490 491template <class Impl> 492bool 493DefaultFetch<Impl>::lookupAndUpdateNextPC( 494 DynInstPtr &inst, TheISA::PCState &nextPC) 495{ 496 // Do branch prediction check here. 497 // A bit of a misnomer...next_PC is actually the current PC until 498 // this function updates it. 499 bool predict_taken; 500 501 if (!inst->isControl()) { 502 TheISA::advancePC(nextPC, inst->staticInst); 503 inst->setPredTarg(nextPC); 504 inst->setPredTaken(false); 505 return false; 506 } 507 508 ThreadID tid = inst->threadNumber; 509 predict_taken = branchPred.predict(inst, nextPC, tid); 510 511 if (predict_taken) { 512 DPRINTF(Fetch, "[tid:%i]: [sn:%i]: Branch predicted to be taken to %s.\n", 513 tid, inst->seqNum, nextPC); 514 } else { 515 DPRINTF(Fetch, "[tid:%i]: [sn:%i]:Branch predicted to be not taken.\n", 516 tid, inst->seqNum); 517 } 518 519 DPRINTF(Fetch, "[tid:%i]: [sn:%i] Branch predicted to go to %s.\n", 520 tid, inst->seqNum, nextPC); 521 inst->setPredTarg(nextPC); 522 inst->setPredTaken(predict_taken); 523 524 ++fetchedBranches; 525 526 if (predict_taken) { 527 ++predictedBranches; 528 } 529 530 return predict_taken; 531} 532 533template <class Impl> 534bool 535DefaultFetch<Impl>::fetchCacheLine(Addr vaddr, ThreadID tid, Addr pc) 536{ 537 Fault fault = NoFault; 538 539 // @todo: not sure if these should block translation. 540 //AlphaDep 541 if (cacheBlocked) { 542 DPRINTF(Fetch, "[tid:%i] Can't fetch cache line, cache blocked\n", 543 tid); 544 return false; 545 } else if (isSwitchedOut()) { 546 DPRINTF(Fetch, "[tid:%i] Can't fetch cache line, switched out\n", 547 tid); 548 return false; 549 } else if (checkInterrupt(pc)) { 550 // Hold off fetch from getting new instructions when: 551 // Cache is blocked, or 552 // while an interrupt is pending and we're not in PAL mode, or 553 // fetch is switched out. 554 DPRINTF(Fetch, "[tid:%i] Can't fetch cache line, interrupt pending\n", 555 tid); 556 return false; 557 } 558 559 // Align the fetch address so it's at the start of a cache block. 560 Addr block_PC = icacheBlockAlignPC(vaddr); 561 562 DPRINTF(Fetch, "[tid:%i] Fetching cache line %#x for addr %#x\n", 563 tid, block_PC, vaddr); 564 565 // Setup the memReq to do a read of the first instruction's address. 566 // Set the appropriate read size and flags as well. 567 // Build request here. 568 RequestPtr mem_req = 569 new Request(tid, block_PC, cacheBlkSize, Request::INST_FETCH, 570 pc, cpu->thread[tid]->contextId(), tid); 571 572 memReq[tid] = mem_req; 573 574 // Initiate translation of the icache block 575 fetchStatus[tid] = ItlbWait; 576 FetchTranslation *trans = new FetchTranslation(this); 577 cpu->itb->translateTiming(mem_req, cpu->thread[tid]->getTC(), 578 trans, BaseTLB::Execute); 579 return true; 580} 581 582template <class Impl> 583void 584DefaultFetch<Impl>::finishTranslation(Fault fault, RequestPtr mem_req) 585{ 586 ThreadID tid = mem_req->threadId(); 587 Addr block_PC = mem_req->getVaddr(); 588 589 // Wake up CPU if it was idle 590 cpu->wakeCPU(); 591 592 if (fetchStatus[tid] != ItlbWait || mem_req != memReq[tid] || 593 mem_req->getVaddr() != memReq[tid]->getVaddr() || isSwitchedOut()) { 594 DPRINTF(Fetch, "[tid:%i] Ignoring itlb completed after squash\n", 595 tid); 596 ++fetchTlbSquashes; 597 delete mem_req; 598 return; 599 } 600 601 602 // If translation was successful, attempt to read the icache block. 603 if (fault == NoFault) { 604 // Check that we're not going off into random memory 605 // If we have, just wait around for commit to squash something and put 606 // us on the right track 607 if (!cpu->system->isMemory(mem_req->getPaddr())) { 608 warn("Address %#x is outside of physical memory, stopping fetch\n", 609 mem_req->getPaddr()); 610 fetchStatus[tid] = NoGoodAddr; 611 delete mem_req; 612 memReq[tid] = NULL; 613 return; 614 } 615 616 // Build packet here. 617 PacketPtr data_pkt = new Packet(mem_req, 618 MemCmd::ReadReq, Packet::Broadcast); 619 data_pkt->dataDynamicArray(new uint8_t[cacheBlkSize]); 620 621 cacheDataPC[tid] = block_PC; 622 cacheDataValid[tid] = false; 623 DPRINTF(Fetch, "Fetch: Doing instruction read.\n"); 624 625 fetchedCacheLines++; 626 627 // Access the cache. 628 if (!cpu->getIcachePort()->sendTiming(data_pkt)) { 629 assert(retryPkt == NULL); 630 assert(retryTid == InvalidThreadID); 631 DPRINTF(Fetch, "[tid:%i] Out of MSHRs!\n", tid); 632 633 fetchStatus[tid] = IcacheWaitRetry; 634 retryPkt = data_pkt; 635 retryTid = tid; 636 cacheBlocked = true; 637 } else { 638 DPRINTF(Fetch, "[tid:%i]: Doing Icache access.\n", tid); 639 DPRINTF(Activity, "[tid:%i]: Activity: Waiting on I-cache " 640 "response.\n", tid); 641 642 lastIcacheStall[tid] = curTick(); 643 fetchStatus[tid] = IcacheWaitResponse; 644 } 645 } else { 646 if (!(numInst < fetchWidth)) { 647 assert(!finishTranslationEvent.scheduled()); 648 finishTranslationEvent.setFault(fault); 649 finishTranslationEvent.setReq(mem_req); 650 cpu->schedule(finishTranslationEvent, cpu->nextCycle(curTick() + cpu->ticks(1))); 651 return; 652 } 653 DPRINTF(Fetch, "[tid:%i] Got back req with addr %#x but expected %#x\n", 654 tid, mem_req->getVaddr(), memReq[tid]->getVaddr()); 655 // Translation faulted, icache request won't be sent. 656 delete mem_req; 657 memReq[tid] = NULL; 658 659 // Send the fault to commit. This thread will not do anything 660 // until commit handles the fault. The only other way it can 661 // wake up is if a squash comes along and changes the PC. 662 TheISA::PCState fetchPC = pc[tid]; 663 664 DPRINTF(Fetch, "[tid:%i]: Translation faulted, building noop.\n", tid); 665 // We will use a nop in ordier to carry the fault. 666 DynInstPtr instruction = buildInst(tid, 667 decoder.decode(TheISA::NoopMachInst, fetchPC.instAddr()), 668 NULL, fetchPC, fetchPC, false); 669 670 instruction->setPredTarg(fetchPC); 671 instruction->fault = fault; 672 wroteToTimeBuffer = true; 673 674 DPRINTF(Activity, "Activity this cycle.\n"); 675 cpu->activityThisCycle(); 676 677 fetchStatus[tid] = TrapPending; 678 679 DPRINTF(Fetch, "[tid:%i]: Blocked, need to handle the trap.\n", tid); 680 DPRINTF(Fetch, "[tid:%i]: fault (%s) detected @ PC %s.\n", 681 tid, fault->name(), pc[tid]); 682 } 683 _status = updateFetchStatus(); 684} 685 686template <class Impl> 687inline void 688DefaultFetch<Impl>::doSquash(const TheISA::PCState &newPC, 689 const DynInstPtr squashInst, ThreadID tid) 690{ 691 DPRINTF(Fetch, "[tid:%i]: Squashing, setting PC to: %s.\n", 692 tid, newPC); 693 694 pc[tid] = newPC; 695 fetchOffset[tid] = 0; 696 if (squashInst && squashInst->pcState().instAddr() == newPC.instAddr()) 697 macroop[tid] = squashInst->macroop; 698 else 699 macroop[tid] = NULL; 700 predecoder.reset(); 701 702 // Clear the icache miss if it's outstanding. 703 if (fetchStatus[tid] == IcacheWaitResponse) { 704 DPRINTF(Fetch, "[tid:%i]: Squashing outstanding Icache miss.\n", 705 tid); 706 memReq[tid] = NULL; 707 } else if (fetchStatus[tid] == ItlbWait) { 708 DPRINTF(Fetch, "[tid:%i]: Squashing outstanding ITLB miss.\n", 709 tid); 710 memReq[tid] = NULL; 711 } 712 713 // Get rid of the retrying packet if it was from this thread. 714 if (retryTid == tid) { 715 assert(cacheBlocked); 716 if (retryPkt) { 717 delete retryPkt->req; 718 delete retryPkt; 719 } 720 retryPkt = NULL; 721 retryTid = InvalidThreadID; 722 } 723 724 fetchStatus[tid] = Squashing; 725 726 ++fetchSquashCycles; 727} 728 729template<class Impl> 730void 731DefaultFetch<Impl>::squashFromDecode(const TheISA::PCState &newPC, 732 const DynInstPtr squashInst, 733 const InstSeqNum seq_num, ThreadID tid) 734{ 735 DPRINTF(Fetch, "[tid:%i]: Squashing from decode.\n", tid); 736 737 doSquash(newPC, squashInst, tid); 738 739 // Tell the CPU to remove any instructions that are in flight between 740 // fetch and decode. 741 cpu->removeInstsUntil(seq_num, tid); 742} 743 744template<class Impl> 745bool 746DefaultFetch<Impl>::checkStall(ThreadID tid) const 747{ 748 bool ret_val = false; 749 750 if (cpu->contextSwitch) { 751 DPRINTF(Fetch,"[tid:%i]: Stalling for a context switch.\n",tid); 752 ret_val = true; 753 } else if (stalls[tid].decode) { 754 DPRINTF(Fetch,"[tid:%i]: Stall from Decode stage detected.\n",tid); 755 ret_val = true; 756 } else if (stalls[tid].rename) { 757 DPRINTF(Fetch,"[tid:%i]: Stall from Rename stage detected.\n",tid); 758 ret_val = true; 759 } else if (stalls[tid].iew) { 760 DPRINTF(Fetch,"[tid:%i]: Stall from IEW stage detected.\n",tid); 761 ret_val = true; 762 } else if (stalls[tid].commit) { 763 DPRINTF(Fetch,"[tid:%i]: Stall from Commit stage detected.\n",tid); 764 ret_val = true; 765 } 766 767 return ret_val; 768} 769 770template<class Impl> 771typename DefaultFetch<Impl>::FetchStatus 772DefaultFetch<Impl>::updateFetchStatus() 773{ 774 //Check Running 775 list<ThreadID>::iterator threads = activeThreads->begin(); 776 list<ThreadID>::iterator end = activeThreads->end(); 777 778 while (threads != end) { 779 ThreadID tid = *threads++; 780 781 if (fetchStatus[tid] == Running || 782 fetchStatus[tid] == Squashing || 783 fetchStatus[tid] == IcacheAccessComplete) { 784 785 if (_status == Inactive) { 786 DPRINTF(Activity, "[tid:%i]: Activating stage.\n",tid); 787 788 if (fetchStatus[tid] == IcacheAccessComplete) { 789 DPRINTF(Activity, "[tid:%i]: Activating fetch due to cache" 790 "completion\n",tid); 791 } 792 793 cpu->activateStage(O3CPU::FetchIdx); 794 } 795 796 return Active; 797 } 798 } 799 800 // Stage is switching from active to inactive, notify CPU of it. 801 if (_status == Active) { 802 DPRINTF(Activity, "Deactivating stage.\n"); 803 804 cpu->deactivateStage(O3CPU::FetchIdx); 805 } 806 807 return Inactive; 808} 809 810template <class Impl> 811void 812DefaultFetch<Impl>::squash(const TheISA::PCState &newPC, 813 const InstSeqNum seq_num, DynInstPtr squashInst, 814 ThreadID tid) 815{ 816 DPRINTF(Fetch, "[tid:%u]: Squash from commit.\n", tid); 817 818 doSquash(newPC, squashInst, tid); 819 820 // Tell the CPU to remove any instructions that are not in the ROB. 821 cpu->removeInstsNotInROB(tid); 822} 823 824template <class Impl> 825void 826DefaultFetch<Impl>::tick() 827{ 828 list<ThreadID>::iterator threads = activeThreads->begin(); 829 list<ThreadID>::iterator end = activeThreads->end(); 830 bool status_change = false; 831 832 wroteToTimeBuffer = false; 833 834 for (ThreadID i = 0; i < Impl::MaxThreads; ++i) { 835 issuePipelinedIfetch[i] = false; 836 } 837 838 while (threads != end) { 839 ThreadID tid = *threads++; 840 841 // Check the signals for each thread to determine the proper status 842 // for each thread. 843 bool updated_status = checkSignalsAndUpdate(tid); 844 status_change = status_change || updated_status; 845 } 846 847 DPRINTF(Fetch, "Running stage.\n"); 848 849 #if FULL_SYSTEM 850 if (fromCommit->commitInfo[0].interruptPending) { 851 interruptPending = true; 852 } 853 854 if (fromCommit->commitInfo[0].clearInterrupt) { 855 interruptPending = false; 856 } 857#endif 858 859 for (threadFetched = 0; threadFetched < numFetchingThreads; 860 threadFetched++) { 861 // Fetch each of the actively fetching threads. 862 fetch(status_change); 863 } 864 865 // Record number of instructions fetched this cycle for distribution. 866 fetchNisnDist.sample(numInst); 867 868 if (status_change) { 869 // Change the fetch stage status if there was a status change. 870 _status = updateFetchStatus(); 871 } 872 873 // If there was activity this cycle, inform the CPU of it. 874 if (wroteToTimeBuffer || cpu->contextSwitch) { 875 DPRINTF(Activity, "Activity this cycle.\n"); 876 877 cpu->activityThisCycle(); 878 } 879 880 // Issue the next I-cache request if possible. 881 for (ThreadID i = 0; i < Impl::MaxThreads; ++i) { 882 if (issuePipelinedIfetch[i]) { 883 pipelineIcacheAccesses(i); 884 } 885 } 886 887 // Reset the number of the instruction we've fetched. 888 numInst = 0; 889} 890 891template <class Impl> 892bool 893DefaultFetch<Impl>::checkSignalsAndUpdate(ThreadID tid) 894{ 895 // Update the per thread stall statuses. 896 if (fromDecode->decodeBlock[tid]) { 897 stalls[tid].decode = true; 898 } 899 900 if (fromDecode->decodeUnblock[tid]) { 901 assert(stalls[tid].decode); 902 assert(!fromDecode->decodeBlock[tid]); 903 stalls[tid].decode = false; 904 } 905 906 if (fromRename->renameBlock[tid]) { 907 stalls[tid].rename = true; 908 } 909 910 if (fromRename->renameUnblock[tid]) { 911 assert(stalls[tid].rename); 912 assert(!fromRename->renameBlock[tid]); 913 stalls[tid].rename = false; 914 } 915 916 if (fromIEW->iewBlock[tid]) { 917 stalls[tid].iew = true; 918 } 919 920 if (fromIEW->iewUnblock[tid]) { 921 assert(stalls[tid].iew); 922 assert(!fromIEW->iewBlock[tid]); 923 stalls[tid].iew = false; 924 } 925 926 if (fromCommit->commitBlock[tid]) { 927 stalls[tid].commit = true; 928 } 929 930 if (fromCommit->commitUnblock[tid]) { 931 assert(stalls[tid].commit); 932 assert(!fromCommit->commitBlock[tid]); 933 stalls[tid].commit = false; 934 } 935 936 // Check squash signals from commit. 937 if (fromCommit->commitInfo[tid].squash) { 938 939 DPRINTF(Fetch, "[tid:%u]: Squashing instructions due to squash " 940 "from commit.\n",tid); 941 // In any case, squash. 942 squash(fromCommit->commitInfo[tid].pc, 943 fromCommit->commitInfo[tid].doneSeqNum, 944 fromCommit->commitInfo[tid].squashInst, tid); 945 946 // If it was a branch mispredict on a control instruction, update the 947 // branch predictor with that instruction, otherwise just kill the 948 // invalid state we generated in after sequence number 949 if (fromCommit->commitInfo[tid].mispredictInst && 950 fromCommit->commitInfo[tid].mispredictInst->isControl()) { 951 branchPred.squash(fromCommit->commitInfo[tid].doneSeqNum, 952 fromCommit->commitInfo[tid].pc, 953 fromCommit->commitInfo[tid].branchTaken, 954 tid); 955 } else { 956 branchPred.squash(fromCommit->commitInfo[tid].doneSeqNum, 957 tid); 958 } 959 960 return true; 961 } else if (fromCommit->commitInfo[tid].doneSeqNum) { 962 // Update the branch predictor if it wasn't a squashed instruction 963 // that was broadcasted. 964 branchPred.update(fromCommit->commitInfo[tid].doneSeqNum, tid); 965 } 966 967 // Check ROB squash signals from commit. 968 if (fromCommit->commitInfo[tid].robSquashing) { 969 DPRINTF(Fetch, "[tid:%u]: ROB is still squashing.\n", tid); 970 971 // Continue to squash. 972 fetchStatus[tid] = Squashing; 973 974 return true; 975 } 976 977 // Check squash signals from decode. 978 if (fromDecode->decodeInfo[tid].squash) { 979 DPRINTF(Fetch, "[tid:%u]: Squashing instructions due to squash " 980 "from decode.\n",tid); 981 982 // Update the branch predictor. 983 if (fromDecode->decodeInfo[tid].branchMispredict) { 984 branchPred.squash(fromDecode->decodeInfo[tid].doneSeqNum, 985 fromDecode->decodeInfo[tid].nextPC, 986 fromDecode->decodeInfo[tid].branchTaken, 987 tid); 988 } else { 989 branchPred.squash(fromDecode->decodeInfo[tid].doneSeqNum, 990 tid); 991 } 992 993 if (fetchStatus[tid] != Squashing) { 994 995 DPRINTF(Fetch, "Squashing from decode with PC = %s\n", 996 fromDecode->decodeInfo[tid].nextPC); 997 // Squash unless we're already squashing 998 squashFromDecode(fromDecode->decodeInfo[tid].nextPC, 999 fromDecode->decodeInfo[tid].squashInst, 1000 fromDecode->decodeInfo[tid].doneSeqNum, 1001 tid); 1002 1003 return true; 1004 } 1005 } 1006 1007 if (checkStall(tid) && 1008 fetchStatus[tid] != IcacheWaitResponse && 1009 fetchStatus[tid] != IcacheWaitRetry) { 1010 DPRINTF(Fetch, "[tid:%i]: Setting to blocked\n",tid); 1011 1012 fetchStatus[tid] = Blocked; 1013 1014 return true; 1015 } 1016 1017 if (fetchStatus[tid] == Blocked || 1018 fetchStatus[tid] == Squashing) { 1019 // Switch status to running if fetch isn't being told to block or 1020 // squash this cycle. 1021 DPRINTF(Fetch, "[tid:%i]: Done squashing, switching to running.\n", 1022 tid); 1023 1024 fetchStatus[tid] = Running; 1025 1026 return true; 1027 } 1028 1029 // If we've reached this point, we have not gotten any signals that 1030 // cause fetch to change its status. Fetch remains the same as before. 1031 return false; 1032} 1033 1034template<class Impl> 1035typename Impl::DynInstPtr 1036DefaultFetch<Impl>::buildInst(ThreadID tid, StaticInstPtr staticInst, 1037 StaticInstPtr curMacroop, TheISA::PCState thisPC, 1038 TheISA::PCState nextPC, bool trace) 1039{ 1040 // Get a sequence number. 1041 InstSeqNum seq = cpu->getAndIncrementInstSeq(); 1042 1043 // Create a new DynInst from the instruction fetched. 1044 DynInstPtr instruction = 1045 new DynInst(staticInst, curMacroop, thisPC, nextPC, seq, cpu); 1046 instruction->setTid(tid); 1047 1048 instruction->setASID(tid); 1049 1050 instruction->setThreadState(cpu->thread[tid]); 1051 1052 DPRINTF(Fetch, "[tid:%i]: Instruction PC %#x (%d) created " 1053 "[sn:%lli].\n", tid, thisPC.instAddr(), 1054 thisPC.microPC(), seq); 1055 1056 DPRINTF(Fetch, "[tid:%i]: Instruction is: %s\n", tid, 1057 instruction->staticInst-> 1058 disassemble(thisPC.instAddr())); 1059 1060#if TRACING_ON 1061 if (trace) { 1062 instruction->traceData = 1063 cpu->getTracer()->getInstRecord(curTick(), cpu->tcBase(tid), 1064 instruction->staticInst, thisPC, curMacroop); 1065 } 1066#else 1067 instruction->traceData = NULL; 1068#endif 1069 1070 // Add instruction to the CPU's list of instructions. 1071 instruction->setInstListIt(cpu->addInst(instruction)); 1072 1073 // Write the instruction to the first slot in the queue 1074 // that heads to decode. 1075 assert(numInst < fetchWidth); 1076 toDecode->insts[toDecode->size++] = instruction; 1077 1078 // Keep track of if we can take an interrupt at this boundary 1079 delayedCommit[tid] = instruction->isDelayedCommit(); 1080 1081 return instruction; 1082} 1083 1084template<class Impl> 1085void 1086DefaultFetch<Impl>::fetch(bool &status_change) 1087{ 1088 ////////////////////////////////////////// 1089 // Start actual fetch 1090 ////////////////////////////////////////// 1091 ThreadID tid = getFetchingThread(fetchPolicy); 1092 1093 if (tid == InvalidThreadID || drainPending) { 1094 // Breaks looping condition in tick() 1095 threadFetched = numFetchingThreads; 1096 1097 if (numThreads == 1) { // @todo Per-thread stats 1098 profileStall(0); 1099 } 1100 1101 return; 1102 } 1103 1104 DPRINTF(Fetch, "Attempting to fetch from [tid:%i]\n", tid); 1105 1106 // The current PC. 1107 TheISA::PCState thisPC = pc[tid]; 1108 1109 Addr pcOffset = fetchOffset[tid]; 1110 Addr fetchAddr = (thisPC.instAddr() + pcOffset) & BaseCPU::PCMask; 1111 1112 bool inRom = isRomMicroPC(thisPC.microPC()); 1113 1114 // If returning from the delay of a cache miss, then update the status 1115 // to running, otherwise do the cache access. Possibly move this up 1116 // to tick() function. 1117 if (fetchStatus[tid] == IcacheAccessComplete) { 1118 DPRINTF(Fetch, "[tid:%i]: Icache miss is complete.\n", tid); 1119 1120 fetchStatus[tid] = Running; 1121 status_change = true; 1122 } else if (fetchStatus[tid] == Running) { 1123 // Align the fetch PC so its at the start of a cache block. 1124 Addr block_PC = icacheBlockAlignPC(fetchAddr); 1125 1126 // If buffer is no longer valid or fetchAddr has moved to point 1127 // to the next cache block, AND we have no remaining ucode 1128 // from a macro-op, then start fetch from icache. 1129 if (!(cacheDataValid[tid] && block_PC == cacheDataPC[tid]) 1130 && !inRom && !macroop[tid]) { 1131 DPRINTF(Fetch, "[tid:%i]: Attempting to translate and read " 1132 "instruction, starting at PC %s.\n", tid, thisPC); 1133 1134 fetchCacheLine(fetchAddr, tid, thisPC.instAddr()); 1135 1136 if (fetchStatus[tid] == IcacheWaitResponse) 1137 ++icacheStallCycles; 1138 else if (fetchStatus[tid] == ItlbWait) 1139 ++fetchTlbCycles; 1140 else 1141 ++fetchMiscStallCycles; 1142 return; 1143 } else if ((checkInterrupt(thisPC.instAddr()) && !delayedCommit[tid]) 1144 || isSwitchedOut()) { 1145 // Stall CPU if an interrupt is posted and we're not issuing 1146 // an delayed commit micro-op currently (delayed commit instructions 1147 // are not interruptable by interrupts, only faults) 1148 ++fetchMiscStallCycles; 1149 return; 1150 } 1151 } else { 1152 if (fetchStatus[tid] == Idle) { 1153 ++fetchIdleCycles; 1154 DPRINTF(Fetch, "[tid:%i]: Fetch is idle!\n", tid); 1155 } 1156 1157 // Status is Idle, so fetch should do nothing. 1158 return; 1159 } 1160 1161 ++fetchCycles; 1162 1163 TheISA::PCState nextPC = thisPC; 1164 1165 StaticInstPtr staticInst = NULL; 1166 StaticInstPtr curMacroop = macroop[tid]; 1167 1168 // If the read of the first instruction was successful, then grab the 1169 // instructions from the rest of the cache line and put them into the 1170 // queue heading to decode. 1171 1172 DPRINTF(Fetch, "[tid:%i]: Adding instructions to queue to " 1173 "decode.\n", tid); 1174 1175 // Need to keep track of whether or not a predicted branch 1176 // ended this fetch block. 1177 bool predictedBranch = false; 1178 1179 TheISA::MachInst *cacheInsts = 1180 reinterpret_cast<TheISA::MachInst *>(cacheData[tid]); 1181 1182 const unsigned numInsts = cacheBlkSize / instSize; 1183 unsigned blkOffset = (fetchAddr - cacheDataPC[tid]) / instSize; 1184 1185 // Loop through instruction memory from the cache. 1186 // Keep issuing while fetchWidth is available and branch is not 1187 // predicted taken 1188 while (numInst < fetchWidth && !predictedBranch) { 1189 1190 // We need to process more memory if we aren't going to get a 1191 // StaticInst from the rom, the current macroop, or what's already 1192 // in the predecoder. 1193 bool needMem = !inRom && !curMacroop && !predecoder.extMachInstReady(); 1194 1195 if (needMem) { 1196 if (blkOffset >= numInsts) { 1197 // We need to process more memory, but we've run out of the 1198 // current block. 1199 break; 1200 } 1201 1202 if (ISA_HAS_DELAY_SLOT && pcOffset == 0) { 1203 // Walk past any annulled delay slot instructions. 1204 Addr pcAddr = thisPC.instAddr() & BaseCPU::PCMask; 1205 while (fetchAddr != pcAddr && blkOffset < numInsts) { 1206 blkOffset++; 1207 fetchAddr += instSize; 1208 } 1209 if (blkOffset >= numInsts) 1210 break; 1211 } 1212 MachInst inst = TheISA::gtoh(cacheInsts[blkOffset]); 1213 1214 predecoder.setTC(cpu->thread[tid]->getTC()); 1215 predecoder.moreBytes(thisPC, fetchAddr, inst); 1216 1217 if (predecoder.needMoreBytes()) { 1218 blkOffset++; 1219 fetchAddr += instSize; 1220 pcOffset += instSize; 1221 } 1222 } 1223 1224 // Extract as many instructions and/or microops as we can from 1225 // the memory we've processed so far. 1226 do { 1227 if (!(curMacroop || inRom)) { 1228 if (predecoder.extMachInstReady()) { 1229 ExtMachInst extMachInst = 1230 predecoder.getExtMachInst(thisPC); 1231 staticInst = 1232 decoder.decode(extMachInst, thisPC.instAddr()); 1233 1234 // Increment stat of fetched instructions. 1235 ++fetchedInsts; 1236 1237 if (staticInst->isMacroop()) { 1238 curMacroop = staticInst; 1239 } else { 1240 pcOffset = 0; 1241 } 1242 } else { 1243 // We need more bytes for this instruction so blkOffset and 1244 // pcOffset will be updated 1245 break; 1246 } 1247 } 1248 // Whether we're moving to a new macroop because we're at the 1249 // end of the current one, or the branch predictor incorrectly 1250 // thinks we are... 1251 bool newMacro = false; 1252 if (curMacroop || inRom) { 1253 if (inRom) { 1254 staticInst = cpu->microcodeRom.fetchMicroop( 1255 thisPC.microPC(), curMacroop); 1256 } else { 1257 staticInst = curMacroop->fetchMicroop(thisPC.microPC()); 1258 } 1259 newMacro |= staticInst->isLastMicroop(); 1260 } 1261 1262 DynInstPtr instruction = 1263 buildInst(tid, staticInst, curMacroop, 1264 thisPC, nextPC, true); 1265 1266 numInst++; 1267 1268#if TRACING_ON 1269 instruction->fetchTick = curTick(); 1270#endif 1271 1272 nextPC = thisPC; 1273 1274 // If we're branching after this instruction, quite fetching 1275 // from the same block then. 1276 predictedBranch |= thisPC.branching(); 1277 predictedBranch |= 1278 lookupAndUpdateNextPC(instruction, nextPC); 1279 if (predictedBranch) { 1280 DPRINTF(Fetch, "Branch detected with PC = %s\n", thisPC); 1281 } 1282 1283 newMacro |= thisPC.instAddr() != nextPC.instAddr(); 1284 1285 // Move to the next instruction, unless we have a branch. 1286 thisPC = nextPC; 1287 1288 if (newMacro) { 1289 fetchAddr = thisPC.instAddr() & BaseCPU::PCMask; 1290 blkOffset = (fetchAddr - cacheDataPC[tid]) / instSize; 1291 pcOffset = 0; 1292 curMacroop = NULL; 1293 } 1294 1295 if (instruction->isQuiesce()) { 1296 DPRINTF(Fetch, 1297 "Quiesce instruction encountered, halting fetch!"); 1298 fetchStatus[tid] = QuiescePending; 1299 status_change = true; 1300 break; 1301 } 1302 } while ((curMacroop || predecoder.extMachInstReady()) && 1303 numInst < fetchWidth); 1304 } 1305 1306 if (predictedBranch) { 1307 DPRINTF(Fetch, "[tid:%i]: Done fetching, predicted branch " 1308 "instruction encountered.\n", tid); 1309 } else if (numInst >= fetchWidth) { 1310 DPRINTF(Fetch, "[tid:%i]: Done fetching, reached fetch bandwidth " 1311 "for this cycle.\n", tid); 1312 } else if (blkOffset >= cacheBlkSize) { 1313 DPRINTF(Fetch, "[tid:%i]: Done fetching, reached the end of cache " 1314 "block.\n", tid); 1315 } 1316 1317 macroop[tid] = curMacroop; 1318 fetchOffset[tid] = pcOffset; 1319 1320 if (numInst > 0) { 1321 wroteToTimeBuffer = true; 1322 } 1323 1324 pc[tid] = thisPC; 1325 1326 // pipeline a fetch if we're crossing a cache boundary and not in 1327 // a state that would preclude fetching 1328 fetchAddr = (thisPC.instAddr() + pcOffset) & BaseCPU::PCMask; 1329 Addr block_PC = icacheBlockAlignPC(fetchAddr); 1330 issuePipelinedIfetch[tid] = block_PC != cacheDataPC[tid] && 1331 fetchStatus[tid] != IcacheWaitResponse && 1332 fetchStatus[tid] != ItlbWait && 1333 fetchStatus[tid] != IcacheWaitRetry && 1334 fetchStatus[tid] != QuiescePending && 1335 !curMacroop; 1336} 1337 1338template<class Impl> 1339void 1340DefaultFetch<Impl>::recvRetry() 1341{ 1342 if (retryPkt != NULL) { 1343 assert(cacheBlocked); 1344 assert(retryTid != InvalidThreadID); 1345 assert(fetchStatus[retryTid] == IcacheWaitRetry); 1346 1347 if (cpu->getIcachePort()->sendTiming(retryPkt)) { 1348 fetchStatus[retryTid] = IcacheWaitResponse; 1349 retryPkt = NULL; 1350 retryTid = InvalidThreadID; 1351 cacheBlocked = false; 1352 } 1353 } else { 1354 assert(retryTid == InvalidThreadID); 1355 // Access has been squashed since it was sent out. Just clear 1356 // the cache being blocked. 1357 cacheBlocked = false; 1358 } 1359} 1360 1361/////////////////////////////////////// 1362// // 1363// SMT FETCH POLICY MAINTAINED HERE // 1364// // 1365/////////////////////////////////////// 1366template<class Impl> 1367ThreadID 1368DefaultFetch<Impl>::getFetchingThread(FetchPriority &fetch_priority) 1369{ 1370 if (numThreads > 1) { 1371 switch (fetch_priority) { 1372 1373 case SingleThread: 1374 return 0; 1375 1376 case RoundRobin: 1377 return roundRobin(); 1378 1379 case IQ: 1380 return iqCount(); 1381 1382 case LSQ: 1383 return lsqCount(); 1384 1385 case Branch: 1386 return branchCount(); 1387 1388 default: 1389 return InvalidThreadID; 1390 } 1391 } else { 1392 list<ThreadID>::iterator thread = activeThreads->begin(); 1393 if (thread == activeThreads->end()) { 1394 return InvalidThreadID; 1395 } 1396 1397 ThreadID tid = *thread; 1398 1399 if (fetchStatus[tid] == Running || 1400 fetchStatus[tid] == IcacheAccessComplete || 1401 fetchStatus[tid] == Idle) { 1402 return tid; 1403 } else { 1404 return InvalidThreadID; 1405 } 1406 } 1407} 1408 1409 1410template<class Impl> 1411ThreadID 1412DefaultFetch<Impl>::roundRobin() 1413{ 1414 list<ThreadID>::iterator pri_iter = priorityList.begin(); 1415 list<ThreadID>::iterator end = priorityList.end(); 1416 1417 ThreadID high_pri; 1418 1419 while (pri_iter != end) { 1420 high_pri = *pri_iter; 1421 1422 assert(high_pri <= numThreads); 1423 1424 if (fetchStatus[high_pri] == Running || 1425 fetchStatus[high_pri] == IcacheAccessComplete || 1426 fetchStatus[high_pri] == Idle) { 1427 1428 priorityList.erase(pri_iter); 1429 priorityList.push_back(high_pri); 1430 1431 return high_pri; 1432 } 1433 1434 pri_iter++; 1435 } 1436 1437 return InvalidThreadID; 1438} 1439 1440template<class Impl> 1441ThreadID 1442DefaultFetch<Impl>::iqCount() 1443{ 1444 std::priority_queue<unsigned> PQ; 1445 std::map<unsigned, ThreadID> threadMap; 1446 1447 list<ThreadID>::iterator threads = activeThreads->begin(); 1448 list<ThreadID>::iterator end = activeThreads->end(); 1449 1450 while (threads != end) { 1451 ThreadID tid = *threads++; 1452 unsigned iqCount = fromIEW->iewInfo[tid].iqCount; 1453 1454 PQ.push(iqCount); 1455 threadMap[iqCount] = tid; 1456 } 1457 1458 while (!PQ.empty()) { 1459 ThreadID high_pri = threadMap[PQ.top()]; 1460 1461 if (fetchStatus[high_pri] == Running || 1462 fetchStatus[high_pri] == IcacheAccessComplete || 1463 fetchStatus[high_pri] == Idle) 1464 return high_pri; 1465 else 1466 PQ.pop(); 1467 1468 } 1469 1470 return InvalidThreadID; 1471} 1472 1473template<class Impl> 1474ThreadID 1475DefaultFetch<Impl>::lsqCount() 1476{ 1477 std::priority_queue<unsigned> PQ; 1478 std::map<unsigned, ThreadID> threadMap; 1479 1480 list<ThreadID>::iterator threads = activeThreads->begin(); 1481 list<ThreadID>::iterator end = activeThreads->end(); 1482 1483 while (threads != end) { 1484 ThreadID tid = *threads++; 1485 unsigned ldstqCount = fromIEW->iewInfo[tid].ldstqCount; 1486 1487 PQ.push(ldstqCount); 1488 threadMap[ldstqCount] = tid; 1489 } 1490 1491 while (!PQ.empty()) { 1492 ThreadID high_pri = threadMap[PQ.top()]; 1493 1494 if (fetchStatus[high_pri] == Running || 1495 fetchStatus[high_pri] == IcacheAccessComplete || 1496 fetchStatus[high_pri] == Idle) 1497 return high_pri; 1498 else 1499 PQ.pop(); 1500 } 1501 1502 return InvalidThreadID; 1503} 1504 1505template<class Impl> 1506ThreadID 1507DefaultFetch<Impl>::branchCount() 1508{ 1509#if 0 1510 list<ThreadID>::iterator thread = activeThreads->begin(); 1511 assert(thread != activeThreads->end()); 1512 ThreadID tid = *thread; 1513#endif 1514 1515 panic("Branch Count Fetch policy unimplemented\n"); 1516 return InvalidThreadID; 1517} 1518 1519template<class Impl> 1520void 1521DefaultFetch<Impl>::pipelineIcacheAccesses(ThreadID tid) 1522{ 1523 if (!issuePipelinedIfetch[tid]) { 1524 return; 1525 } 1526 1527 // The next PC to access. 1528 TheISA::PCState thisPC = pc[tid]; 1529 1530 if (isRomMicroPC(thisPC.microPC())) { 1531 return; 1532 } 1533 1534 Addr pcOffset = fetchOffset[tid]; 1535 Addr fetchAddr = (thisPC.instAddr() + pcOffset) & BaseCPU::PCMask; 1536 1537 // Align the fetch PC so its at the start of a cache block. 1538 Addr block_PC = icacheBlockAlignPC(fetchAddr); 1539 1540 // Unless buffer already got the block, fetch it from icache. 1541 if (!(cacheDataValid[tid] && block_PC == cacheDataPC[tid])) { 1542 DPRINTF(Fetch, "[tid:%i]: Issuing a pipelined I-cache access, " 1543 "starting at PC %s.\n", tid, thisPC); 1544 1545 fetchCacheLine(fetchAddr, tid, thisPC.instAddr()); 1546 } 1547} 1548 1549template<class Impl> 1550void 1551DefaultFetch<Impl>::profileStall(ThreadID tid) { 1552 DPRINTF(Fetch,"There are no more threads available to fetch from.\n"); 1553 1554 // @todo Per-thread stats 1555 1556 if (drainPending) { 1557 ++fetchPendingDrainCycles; 1558 DPRINTF(Fetch, "Fetch is waiting for a drain!\n"); 1559 } else if (activeThreads->empty()) { 1560 ++fetchNoActiveThreadStallCycles; 1561 DPRINTF(Fetch, "Fetch has no active thread!\n"); 1562 } else if (fetchStatus[tid] == Blocked) { 1563 ++fetchBlockedCycles; 1564 DPRINTF(Fetch, "[tid:%i]: Fetch is blocked!\n", tid); 1565 } else if (fetchStatus[tid] == Squashing) { 1566 ++fetchSquashCycles; 1567 DPRINTF(Fetch, "[tid:%i]: Fetch is squashing!\n", tid); 1568 } else if (fetchStatus[tid] == IcacheWaitResponse) { 1569 ++icacheStallCycles; 1570 DPRINTF(Fetch, "[tid:%i]: Fetch is waiting cache response!\n", 1571 tid); 1572 } else if (fetchStatus[tid] == ItlbWait) { 1573 ++fetchTlbCycles; 1574 DPRINTF(Fetch, "[tid:%i]: Fetch is waiting ITLB walk to " 1575 "finish!\n", tid); 1576 } else if (fetchStatus[tid] == TrapPending) { 1577 ++fetchPendingTrapStallCycles; 1578 DPRINTF(Fetch, "[tid:%i]: Fetch is waiting for a pending trap!\n", 1579 tid); 1580 } else if (fetchStatus[tid] == QuiescePending) { 1581 ++fetchPendingQuiesceStallCycles; 1582 DPRINTF(Fetch, "[tid:%i]: Fetch is waiting for a pending quiesce " 1583 "instruction!\n", tid); 1584 } else if (fetchStatus[tid] == IcacheWaitRetry) { 1585 ++fetchIcacheWaitRetryStallCycles; 1586 DPRINTF(Fetch, "[tid:%i]: Fetch is waiting for an I-cache retry!\n", 1587 tid); 1588 } else if (fetchStatus[tid] == NoGoodAddr) { 1589 DPRINTF(Fetch, "[tid:%i]: Fetch predicted non-executable address\n", 1590 tid); 1591 } else { 1592 DPRINTF(Fetch, "[tid:%i]: Unexpected fetch stall reason (Status: %i).\n", 1593 tid, fetchStatus[tid]); 1594 } 1595} 1596