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