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 --- 35 unchanged lines hidden (view full) --- 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/base.hh" |
53#include "cpu/checker/cpu.hh" 54#include "cpu/o3/fetch.hh" 55#include "cpu/exetrace.hh" 56#include "debug/Activity.hh" 57#include "debug/Fetch.hh" 58#include "mem/packet.hh" 59#include "mem/request.hh" 60#include "params/DerivO3CPU.hh" 61#include "sim/byteswap.hh" 62#include "sim/core.hh" |
63#include "sim/eventq.hh" |
64 65#if FULL_SYSTEM 66#include "arch/tlb.hh" 67#include "arch/vtophys.hh" 68#include "sim/system.hh" 69#endif // FULL_SYSTEM 70 71using namespace std; --- 60 unchanged lines hidden (view full) --- 132 fetch->recvRetry(); 133} 134 135template<class Impl> 136DefaultFetch<Impl>::DefaultFetch(O3CPU *_cpu, DerivO3CPUParams *params) 137 : cpu(_cpu), 138 branchPred(params), 139 predecoder(NULL), |
140 numInst(0), |
141 decodeToFetchDelay(params->decodeToFetchDelay), 142 renameToFetchDelay(params->renameToFetchDelay), 143 iewToFetchDelay(params->iewToFetchDelay), 144 commitToFetchDelay(params->commitToFetchDelay), 145 fetchWidth(params->fetchWidth), 146 cacheBlocked(false), 147 retryPkt(NULL), 148 retryTid(InvalidThreadID), 149 numThreads(params->numThreads), 150 numFetchingThreads(params->smtNumFetchingThreads), 151 interruptPending(false), 152 drainPending(false), |
153 switchedOut(false), 154 finishTranslationEvent(this) |
155{ 156 if (numThreads > Impl::MaxThreads) 157 fatal("numThreads (%d) is larger than compiled limit (%d),\n" 158 "\tincrease MaxThreads in src/cpu/o3/impl.hh\n", 159 numThreads, static_cast<int>(Impl::MaxThreads)); 160 161 // Set fetch stage's status to inactive. 162 _status = Inactive; --- 104 unchanged lines hidden (view full) --- 267 .prereq(fetchedCacheLines); 268 269 fetchMiscStallCycles 270 .name(name() + ".MiscStallCycles") 271 .desc("Number of cycles fetch has spent waiting on interrupts, or " 272 "bad addresses, or out of MSHRs") 273 .prereq(fetchMiscStallCycles); 274 |
275 fetchPendingDrainCycles 276 .name(name() + ".PendingDrainCycles") 277 .desc("Number of cycles fetch has spent waiting on pipes to drain") 278 .prereq(fetchPendingDrainCycles); 279 280 fetchNoActiveThreadStallCycles 281 .name(name() + ".NoActiveThreadStallCycles") 282 .desc("Number of stall cycles due to no active thread to fetch from") 283 .prereq(fetchNoActiveThreadStallCycles); 284 285 fetchPendingTrapStallCycles 286 .name(name() + ".PendingTrapStallCycles") 287 .desc("Number of stall cycles due to pending traps") 288 .prereq(fetchPendingTrapStallCycles); 289 290 fetchPendingQuiesceStallCycles 291 .name(name() + ".PendingQuiesceStallCycles") 292 .desc("Number of stall cycles due to pending quiesce instructions") 293 .prereq(fetchPendingQuiesceStallCycles); 294 295 fetchIcacheWaitRetryStallCycles 296 .name(name() + ".IcacheWaitRetryStallCycles") 297 .desc("Number of stall cycles due to full MSHR") 298 .prereq(fetchIcacheWaitRetryStallCycles); 299 |
300 fetchIcacheSquashes 301 .name(name() + ".IcacheSquashes") 302 .desc("Number of outstanding Icache misses that were squashed") 303 .prereq(fetchIcacheSquashes); 304 305 fetchTlbSquashes 306 .name(name() + ".ItlbSquashes") 307 .desc("Number of outstanding ITLB misses that were squashed") --- 391 unchanged lines hidden (view full) --- 699 DPRINTF(Fetch, "[tid:%i]: Doing Icache access.\n", tid); 700 DPRINTF(Activity, "[tid:%i]: Activity: Waiting on I-cache " 701 "response.\n", tid); 702 703 lastIcacheStall[tid] = curTick(); 704 fetchStatus[tid] = IcacheWaitResponse; 705 } 706 } else { |
707 if (!(numInst < fetchWidth)) { 708 assert(!finishTranslationEvent.scheduled()); 709 finishTranslationEvent.setFault(fault); 710 finishTranslationEvent.setReq(mem_req); 711 cpu->schedule(finishTranslationEvent, cpu->nextCycle(curTick() + cpu->ticks(1))); 712 return; 713 } |
714 DPRINTF(Fetch, "[tid:%i] Got back req with addr %#x but expected %#x\n", |
715 tid, mem_req->getVaddr(), memReq[tid]->getVaddr()); |
716 // Translation faulted, icache request won't be sent. 717 delete mem_req; 718 memReq[tid] = NULL; 719 720 // Send the fault to commit. This thread will not do anything 721 // until commit handles the fault. The only other way it can 722 // wake up is if a squash comes along and changes the PC. 723 TheISA::PCState fetchPC = pc[tid]; --- 158 unchanged lines hidden (view full) --- 882DefaultFetch<Impl>::tick() 883{ 884 list<ThreadID>::iterator threads = activeThreads->begin(); 885 list<ThreadID>::iterator end = activeThreads->end(); 886 bool status_change = false; 887 888 wroteToTimeBuffer = false; 889 |
890 for (ThreadID i = 0; i < Impl::MaxThreads; ++i) { 891 issuePipelinedIfetch[i] = false; 892 } 893 |
894 while (threads != end) { 895 ThreadID tid = *threads++; 896 897 // Check the signals for each thread to determine the proper status 898 // for each thread. 899 bool updated_status = checkSignalsAndUpdate(tid); 900 status_change = status_change || updated_status; 901 } 902 903 DPRINTF(Fetch, "Running stage.\n"); 904 |
905 #if FULL_SYSTEM |
906 if (fromCommit->commitInfo[0].interruptPending) { 907 interruptPending = true; 908 } 909 910 if (fromCommit->commitInfo[0].clearInterrupt) { 911 interruptPending = false; 912 } 913#endif --- 13 unchanged lines hidden (view full) --- 927 } 928 929 // If there was activity this cycle, inform the CPU of it. 930 if (wroteToTimeBuffer || cpu->contextSwitch) { 931 DPRINTF(Activity, "Activity this cycle.\n"); 932 933 cpu->activityThisCycle(); 934 } |
935 936 // Issue the next I-cache request if possible. 937 for (ThreadID i = 0; i < Impl::MaxThreads; ++i) { 938 if (issuePipelinedIfetch[i]) { 939 pipelineIcacheAccesses(i); 940 } 941 } 942 943 // Reset the number of the instruction we've fetched. 944 numInst = 0; |
945} 946 947template <class Impl> 948bool 949DefaultFetch<Impl>::checkSignalsAndUpdate(ThreadID tid) 950{ 951 // Update the per thread stall statuses. 952 if (fromDecode->decodeBlock[tid]) { --- 188 unchanged lines hidden (view full) --- 1141DefaultFetch<Impl>::fetch(bool &status_change) 1142{ 1143 ////////////////////////////////////////// 1144 // Start actual fetch 1145 ////////////////////////////////////////// 1146 ThreadID tid = getFetchingThread(fetchPolicy); 1147 1148 if (tid == InvalidThreadID || drainPending) { |
1149 // Breaks looping condition in tick() 1150 threadFetched = numFetchingThreads; |
1151 1152 if (numThreads == 1) { // @todo Per-thread stats 1153 profileStall(0); 1154 } 1155 |
1156 return; 1157 } 1158 1159 DPRINTF(Fetch, "Attempting to fetch from [tid:%i]\n", tid); 1160 1161 // The current PC. 1162 TheISA::PCState thisPC = pc[tid]; 1163 --- 38 unchanged lines hidden (view full) --- 1202 // are not interruptable by interrupts, only faults) 1203 ++fetchMiscStallCycles; 1204 return; 1205 } 1206 } else { 1207 if (fetchStatus[tid] == Idle) { 1208 ++fetchIdleCycles; 1209 DPRINTF(Fetch, "[tid:%i]: Fetch is idle!\n", tid); |
1210 } 1211 |
1212 // Status is Idle, so fetch should do nothing. |
1213 return; 1214 } 1215 1216 ++fetchCycles; 1217 1218 TheISA::PCState nextPC = thisPC; 1219 1220 StaticInstPtr staticInst = NULL; --- 130 unchanged lines hidden (view full) --- 1351 macroop[tid] = curMacroop; 1352 fetchOffset[tid] = pcOffset; 1353 1354 if (numInst > 0) { 1355 wroteToTimeBuffer = true; 1356 } 1357 1358 pc[tid] = thisPC; |
1359 1360 // pipeline a fetch if we're crossing a cache boundary and not in 1361 // a state that would preclude fetching 1362 fetchAddr = (thisPC.instAddr() + pcOffset) & BaseCPU::PCMask; 1363 Addr block_PC = icacheBlockAlignPC(fetchAddr); 1364 issuePipelinedIfetch[tid] = block_PC != cacheDataPC[tid] && 1365 fetchStatus[tid] != IcacheWaitResponse && 1366 fetchStatus[tid] != ItlbWait && 1367 fetchStatus[tid] != IcacheWaitRetry && 1368 fetchStatus[tid] != QuiescePending && 1369 !curMacroop; |
1370} 1371 1372template<class Impl> 1373void 1374DefaultFetch<Impl>::recvRetry() 1375{ 1376 if (retryPkt != NULL) { 1377 assert(cacheBlocked); --- 166 unchanged lines hidden (view full) --- 1544 list<ThreadID>::iterator thread = activeThreads->begin(); 1545 assert(thread != activeThreads->end()); 1546 ThreadID tid = *thread; 1547#endif 1548 1549 panic("Branch Count Fetch policy unimplemented\n"); 1550 return InvalidThreadID; 1551} |
1552 1553template<class Impl> 1554void 1555DefaultFetch<Impl>::pipelineIcacheAccesses(ThreadID tid) 1556{ 1557 if (!issuePipelinedIfetch[tid]) { 1558 return; 1559 } 1560 1561 // The next PC to access. 1562 TheISA::PCState thisPC = pc[tid]; 1563 1564 if (isRomMicroPC(thisPC.microPC())) { 1565 return; 1566 } 1567 1568 Addr pcOffset = fetchOffset[tid]; 1569 Addr fetchAddr = (thisPC.instAddr() + pcOffset) & BaseCPU::PCMask; 1570 1571 // Align the fetch PC so its at the start of a cache block. 1572 Addr block_PC = icacheBlockAlignPC(fetchAddr); 1573 1574 // Unless buffer already got the block, fetch it from icache. 1575 if (!(cacheDataValid[tid] && block_PC == cacheDataPC[tid])) { 1576 DPRINTF(Fetch, "[tid:%i]: Issuing a pipelined I-cache access, " 1577 "starting at PC %s.\n", tid, thisPC); 1578 1579 fetchCacheLine(fetchAddr, tid, thisPC.instAddr()); 1580 } 1581} 1582 1583template<class Impl> 1584void 1585DefaultFetch<Impl>::profileStall(ThreadID tid) { 1586 DPRINTF(Fetch,"There are no more threads available to fetch from.\n"); 1587 1588 // @todo Per-thread stats 1589 1590 if (drainPending) { 1591 ++fetchPendingDrainCycles; 1592 DPRINTF(Fetch, "Fetch is waiting for a drain!\n"); 1593 } else if (activeThreads->empty()) { 1594 ++fetchNoActiveThreadStallCycles; 1595 DPRINTF(Fetch, "Fetch has no active thread!\n"); 1596 } else if (fetchStatus[tid] == Blocked) { 1597 ++fetchBlockedCycles; 1598 DPRINTF(Fetch, "[tid:%i]: Fetch is blocked!\n", tid); 1599 } else if (fetchStatus[tid] == Squashing) { 1600 ++fetchSquashCycles; 1601 DPRINTF(Fetch, "[tid:%i]: Fetch is squashing!\n", tid); 1602 } else if (fetchStatus[tid] == IcacheWaitResponse) { 1603 ++icacheStallCycles; 1604 DPRINTF(Fetch, "[tid:%i]: Fetch is waiting cache response!\n", 1605 tid); 1606 } else if (fetchStatus[tid] == ItlbWait) { 1607 ++fetchTlbCycles; 1608 DPRINTF(Fetch, "[tid:%i]: Fetch is waiting ITLB walk to " 1609 "finish!\n", tid); 1610 } else if (fetchStatus[tid] == TrapPending) { 1611 ++fetchPendingTrapStallCycles; 1612 DPRINTF(Fetch, "[tid:%i]: Fetch is waiting for a pending trap!\n", 1613 tid); 1614 } else if (fetchStatus[tid] == QuiescePending) { 1615 ++fetchPendingQuiesceStallCycles; 1616 DPRINTF(Fetch, "[tid:%i]: Fetch is waiting for a pending quiesce " 1617 "instruction!\n", tid); 1618 } else if (fetchStatus[tid] == IcacheWaitRetry) { 1619 ++fetchIcacheWaitRetryStallCycles; 1620 DPRINTF(Fetch, "[tid:%i]: Fetch is waiting for an I-cache retry!\n", 1621 tid); 1622 } else if (fetchStatus[tid] == NoGoodAddr) { 1623 DPRINTF(Fetch, "[tid:%i]: Fetch predicted non-executable address\n", 1624 tid); 1625 } else { 1626 DPRINTF(Fetch, "[tid:%i]: Unexpected fetch stall reason (Status: %i).\n", 1627 tid, fetchStatus[tid]); 1628 } 1629} |