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