decode_impl.hh (2654:9559cfa91b9d) decode_impl.hh (2665:a124942bacb8)
1/*
1/*
2 * Copyright (c) 2004-2006 The Regents of The University of Michigan
2 * Copyright (c) 2004-2005 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

--- 8 unchanged lines hidden (view full) ---

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.
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

--- 8 unchanged lines hidden (view full) ---

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
27 */
28
29#include "cpu/o3/decode.hh"
30
29 */
30
31#include "cpu/o3/decode.hh"
32
31using namespace std;
32
33template<class Impl>
33template<class Impl>
34DefaultDecode<Impl>::DefaultDecode(Params *params)
35 : renameToDecodeDelay(params->renameToDecodeDelay),
36 iewToDecodeDelay(params->iewToDecodeDelay),
37 commitToDecodeDelay(params->commitToDecodeDelay),
38 fetchToDecodeDelay(params->fetchToDecodeDelay),
39 decodeWidth(params->decodeWidth),
40 numThreads(params->numberOfThreads)
34SimpleDecode<Impl>::SimpleDecode(Params &params)
35 : renameToDecodeDelay(params.renameToDecodeDelay),
36 iewToDecodeDelay(params.iewToDecodeDelay),
37 commitToDecodeDelay(params.commitToDecodeDelay),
38 fetchToDecodeDelay(params.fetchToDecodeDelay),
39 decodeWidth(params.decodeWidth),
40 numInst(0)
41{
41{
42 _status = Inactive;
43
44 for (int i = 0; i < numThreads; ++i) {
45 decodeStatus[i] = Idle;
46
47 stalls[i].rename = false;
48 stalls[i].iew = false;
49 stalls[i].commit = false;
50 }
51
52 // @todo: Make into a parameter
53 skidBufferMax = (fetchToDecodeDelay * params->fetchWidth) + decodeWidth;
42 DPRINTF(Decode, "Decode: decodeWidth=%i.\n", decodeWidth);
43 _status = Idle;
54}
55
56template <class Impl>
44}
45
46template <class Impl>
57std::string
58DefaultDecode<Impl>::name() const
59{
60 return cpu->name() + ".decode";
61}
62
63template <class Impl>
64void
47void
65DefaultDecode<Impl>::regStats()
48SimpleDecode<Impl>::regStats()
66{
67 decodeIdleCycles
49{
50 decodeIdleCycles
68 .name(name() + ".DECODE:IdleCycles")
51 .name(name() + ".decodeIdleCycles")
69 .desc("Number of cycles decode is idle")
70 .prereq(decodeIdleCycles);
71 decodeBlockedCycles
52 .desc("Number of cycles decode is idle")
53 .prereq(decodeIdleCycles);
54 decodeBlockedCycles
72 .name(name() + ".DECODE:BlockedCycles")
55 .name(name() + ".decodeBlockedCycles")
73 .desc("Number of cycles decode is blocked")
74 .prereq(decodeBlockedCycles);
56 .desc("Number of cycles decode is blocked")
57 .prereq(decodeBlockedCycles);
75 decodeRunCycles
76 .name(name() + ".DECODE:RunCycles")
77 .desc("Number of cycles decode is running")
78 .prereq(decodeRunCycles);
79 decodeUnblockCycles
58 decodeUnblockCycles
80 .name(name() + ".DECODE:UnblockCycles")
59 .name(name() + ".decodeUnblockCycles")
81 .desc("Number of cycles decode is unblocking")
82 .prereq(decodeUnblockCycles);
83 decodeSquashCycles
60 .desc("Number of cycles decode is unblocking")
61 .prereq(decodeUnblockCycles);
62 decodeSquashCycles
84 .name(name() + ".DECODE:SquashCycles")
63 .name(name() + ".decodeSquashCycles")
85 .desc("Number of cycles decode is squashing")
86 .prereq(decodeSquashCycles);
64 .desc("Number of cycles decode is squashing")
65 .prereq(decodeSquashCycles);
87 decodeBranchResolved
88 .name(name() + ".DECODE:BranchResolved")
89 .desc("Number of times decode resolved a branch")
90 .prereq(decodeBranchResolved);
91 decodeBranchMispred
66 decodeBranchMispred
92 .name(name() + ".DECODE:BranchMispred")
67 .name(name() + ".decodeBranchMispred")
93 .desc("Number of times decode detected a branch misprediction")
94 .prereq(decodeBranchMispred);
95 decodeControlMispred
68 .desc("Number of times decode detected a branch misprediction")
69 .prereq(decodeBranchMispred);
70 decodeControlMispred
96 .name(name() + ".DECODE:ControlMispred")
71 .name(name() + ".decodeControlMispred")
97 .desc("Number of times decode detected an instruction incorrectly"
98 " predicted as a control")
99 .prereq(decodeControlMispred);
100 decodeDecodedInsts
72 .desc("Number of times decode detected an instruction incorrectly"
73 " predicted as a control")
74 .prereq(decodeControlMispred);
75 decodeDecodedInsts
101 .name(name() + ".DECODE:DecodedInsts")
76 .name(name() + ".decodeDecodedInsts")
102 .desc("Number of instructions handled by decode")
103 .prereq(decodeDecodedInsts);
104 decodeSquashedInsts
77 .desc("Number of instructions handled by decode")
78 .prereq(decodeDecodedInsts);
79 decodeSquashedInsts
105 .name(name() + ".DECODE:SquashedInsts")
80 .name(name() + ".decodeSquashedInsts")
106 .desc("Number of squashed instructions handled by decode")
107 .prereq(decodeSquashedInsts);
108}
109
110template<class Impl>
111void
81 .desc("Number of squashed instructions handled by decode")
82 .prereq(decodeSquashedInsts);
83}
84
85template<class Impl>
86void
112DefaultDecode<Impl>::setCPU(FullCPU *cpu_ptr)
87SimpleDecode<Impl>::setCPU(FullCPU *cpu_ptr)
113{
88{
114 DPRINTF(Decode, "Setting CPU pointer.\n");
89 DPRINTF(Decode, "Decode: Setting CPU pointer.\n");
115 cpu = cpu_ptr;
116}
117
118template<class Impl>
119void
90 cpu = cpu_ptr;
91}
92
93template<class Impl>
94void
120DefaultDecode<Impl>::setTimeBuffer(TimeBuffer<TimeStruct> *tb_ptr)
95SimpleDecode<Impl>::setTimeBuffer(TimeBuffer<TimeStruct> *tb_ptr)
121{
96{
122 DPRINTF(Decode, "Setting time buffer pointer.\n");
97 DPRINTF(Decode, "Decode: Setting time buffer pointer.\n");
123 timeBuffer = tb_ptr;
124
125 // Setup wire to write information back to fetch.
126 toFetch = timeBuffer->getWire(0);
127
128 // Create wires to get information from proper places in time buffer.
129 fromRename = timeBuffer->getWire(-renameToDecodeDelay);
130 fromIEW = timeBuffer->getWire(-iewToDecodeDelay);
131 fromCommit = timeBuffer->getWire(-commitToDecodeDelay);
132}
133
134template<class Impl>
135void
98 timeBuffer = tb_ptr;
99
100 // Setup wire to write information back to fetch.
101 toFetch = timeBuffer->getWire(0);
102
103 // Create wires to get information from proper places in time buffer.
104 fromRename = timeBuffer->getWire(-renameToDecodeDelay);
105 fromIEW = timeBuffer->getWire(-iewToDecodeDelay);
106 fromCommit = timeBuffer->getWire(-commitToDecodeDelay);
107}
108
109template<class Impl>
110void
136DefaultDecode<Impl>::setDecodeQueue(TimeBuffer<DecodeStruct> *dq_ptr)
111SimpleDecode<Impl>::setDecodeQueue(TimeBuffer<DecodeStruct> *dq_ptr)
137{
112{
138 DPRINTF(Decode, "Setting decode queue pointer.\n");
113 DPRINTF(Decode, "Decode: Setting decode queue pointer.\n");
139 decodeQueue = dq_ptr;
140
141 // Setup wire to write information to proper place in decode queue.
142 toRename = decodeQueue->getWire(0);
143}
144
145template<class Impl>
146void
114 decodeQueue = dq_ptr;
115
116 // Setup wire to write information to proper place in decode queue.
117 toRename = decodeQueue->getWire(0);
118}
119
120template<class Impl>
121void
147DefaultDecode<Impl>::setFetchQueue(TimeBuffer<FetchStruct> *fq_ptr)
122SimpleDecode<Impl>::setFetchQueue(TimeBuffer<FetchStruct> *fq_ptr)
148{
123{
149 DPRINTF(Decode, "Setting fetch queue pointer.\n");
124 DPRINTF(Decode, "Decode: Setting fetch queue pointer.\n");
150 fetchQueue = fq_ptr;
151
152 // Setup wire to read information from fetch queue.
153 fromFetch = fetchQueue->getWire(-fetchToDecodeDelay);
154}
155
156template<class Impl>
125 fetchQueue = fq_ptr;
126
127 // Setup wire to read information from fetch queue.
128 fromFetch = fetchQueue->getWire(-fetchToDecodeDelay);
129}
130
131template<class Impl>
157void
158DefaultDecode<Impl>::setActiveThreads(list<unsigned> *at_ptr)
159{
160 DPRINTF(Decode, "Setting active threads list pointer.\n");
161 activeThreads = at_ptr;
162}
163
164template <class Impl>
165void
166DefaultDecode<Impl>::switchOut()
167{
168 cpu->signalSwitched();
169}
170
171template <class Impl>
172void
173DefaultDecode<Impl>::takeOverFrom()
174{
175 _status = Inactive;
176
177 for (int i = 0; i < numThreads; ++i) {
178 decodeStatus[i] = Idle;
179
180 stalls[i].rename = false;
181 stalls[i].iew = false;
182 stalls[i].commit = false;
183 while (!insts[i].empty())
184 insts[i].pop();
185 while (!skidBuffer[i].empty())
186 skidBuffer[i].pop();
187 branchCount[i] = 0;
188 }
189 wroteToTimeBuffer = false;
190}
191
192template<class Impl>
193bool
194DefaultDecode<Impl>::checkStall(unsigned tid) const
195{
196 bool ret_val = false;
197
198 if (stalls[tid].rename) {
199 DPRINTF(Decode,"[tid:%i]: Stall fom Rename stage detected.\n", tid);
200 ret_val = true;
201 } else if (stalls[tid].iew) {
202 DPRINTF(Decode,"[tid:%i]: Stall fom IEW stage detected.\n", tid);
203 ret_val = true;
204 } else if (stalls[tid].commit) {
205 DPRINTF(Decode,"[tid:%i]: Stall fom Commit stage detected.\n", tid);
206 ret_val = true;
207 }
208
209 return ret_val;
210}
211
212template<class Impl>
213inline bool
132inline bool
214DefaultDecode<Impl>::fetchInstsValid()
133SimpleDecode<Impl>::fetchInstsValid()
215{
216 return fromFetch->size > 0;
217}
218
219template<class Impl>
134{
135 return fromFetch->size > 0;
136}
137
138template<class Impl>
220bool
221DefaultDecode<Impl>::block(unsigned tid)
139void
140SimpleDecode<Impl>::block()
222{
141{
223 DPRINTF(Decode, "[tid:%u]: Blocking.\n", tid);
142 DPRINTF(Decode, "Decode: Blocking.\n");
224
143
225 // If the decode status is blocked or unblocking then decode has not yet
226 // signalled fetch to unblock. In that case, there is no need to tell
227 // fetch to block.
228 if (decodeStatus[tid] != Blocked &&
229 decodeStatus[tid] != Unblocking) {
230 toFetch->decodeBlock[tid] = true;
231 wroteToTimeBuffer = true;
232 }
144 // Set the status to Blocked.
145 _status = Blocked;
233
234 // Add the current inputs to the skid buffer so they can be
235 // reprocessed when this stage unblocks.
146
147 // Add the current inputs to the skid buffer so they can be
148 // reprocessed when this stage unblocks.
236 skidInsert(tid);
149 skidBuffer.push(*fromFetch);
237
150
238 if (decodeStatus[tid] != Blocked) {
239 // Set the status to Blocked.
240 decodeStatus[tid] = Blocked;
241 return true;
242 }
243
244 return false;
151 // Note that this stage only signals previous stages to stall when
152 // it is the cause of the stall originates at this stage. Otherwise
153 // the previous stages are expected to check all possible stall signals.
245}
246
247template<class Impl>
154}
155
156template<class Impl>
248bool
249DefaultDecode<Impl>::unblock(unsigned tid)
157inline void
158SimpleDecode<Impl>::unblock()
250{
159{
251 // Decode is done unblocking only if the skid buffer is empty.
252 if (skidBuffer[tid].empty()) {
253 DPRINTF(Decode, "[tid:%u]: Done unblocking.\n", tid);
254 toFetch->decodeUnblock[tid] = true;
255 wroteToTimeBuffer = true;
160 DPRINTF(Decode, "Decode: Unblocking, going to remove "
161 "instructions from skid buffer.\n");
162 // Remove the now processed instructions from the skid buffer.
163 skidBuffer.pop();
256
164
257 decodeStatus[tid] = Running;
258 return true;
165 // If there's still information in the skid buffer, then
166 // continue to tell previous stages to stall. They will be
167 // able to restart once the skid buffer is empty.
168 if (!skidBuffer.empty()) {
169 toFetch->decodeInfo.stall = true;
170 } else {
171 DPRINTF(Decode, "Decode: Finished unblocking.\n");
172 _status = Running;
259 }
173 }
260
261 DPRINTF(Decode, "[tid:%u]: Currently unblocking.\n", tid);
262
263 return false;
264}
265
174}
175
176// This squash is specifically for when Decode detects a PC-relative branch
177// was predicted incorrectly.
266template<class Impl>
267void
178template<class Impl>
179void
268DefaultDecode<Impl>::squash(DynInstPtr &inst, unsigned tid)
180SimpleDecode<Impl>::squash(DynInstPtr &inst)
269{
181{
270 DPRINTF(Decode, "[tid:%i]: Squashing due to incorrect branch prediction "
271 "detected at decode.\n", tid);
182 DPRINTF(Decode, "Decode: Squashing due to incorrect branch prediction "
183 "detected at decode.\n");
184 Addr new_PC = inst->readNextPC();
272
185
273 toFetch->decodeInfo[tid].branchMispredict = true;
274 toFetch->decodeInfo[tid].doneSeqNum = inst->seqNum;
275 toFetch->decodeInfo[tid].predIncorrect = true;
276 toFetch->decodeInfo[tid].squash = true;
277 toFetch->decodeInfo[tid].nextPC = inst->readNextPC();
278 toFetch->decodeInfo[tid].branchTaken = true;
186 toFetch->decodeInfo.branchMispredict = true;
187 toFetch->decodeInfo.doneSeqNum = inst->seqNum;
188 toFetch->decodeInfo.predIncorrect = true;
189 toFetch->decodeInfo.squash = true;
190 toFetch->decodeInfo.nextPC = new_PC;
191 toFetch->decodeInfo.branchTaken = true;
279
192
280 if (decodeStatus[tid] == Blocked ||
281 decodeStatus[tid] == Unblocking) {
282 toFetch->decodeUnblock[tid] = 1;
283 }
284
285 // Set status to squashing.
193 // Set status to squashing.
286 decodeStatus[tid] = Squashing;
194 _status = Squashing;
287
195
288 for (int i=0; i<fromFetch->size; i++) {
289 if (fromFetch->insts[i]->threadNumber == tid &&
290 fromFetch->insts[i]->seqNum > inst->seqNum) {
291 fromFetch->insts[i]->squashed = true;
292 }
293 }
294
295 while (!insts[tid].empty()) {
296 insts[tid].pop();
297 }
298
299 // Clear the skid buffer in case it has any data in it.
196 // Clear the skid buffer in case it has any data in it.
300 while (!skidBuffer[tid].empty()) {
301 skidBuffer[tid].pop();
197 while (!skidBuffer.empty()) {
198 skidBuffer.pop();
302 }
303
304 // Squash instructions up until this one
199 }
200
201 // Squash instructions up until this one
305 cpu->removeInstsUntil(inst->seqNum, tid);
202 // Slightly unrealistic!
203 cpu->removeInstsUntil(inst->seqNum);
306}
307
308template<class Impl>
204}
205
206template<class Impl>
309unsigned
310DefaultDecode<Impl>::squash(unsigned tid)
207void
208SimpleDecode<Impl>::squash()
311{
209{
312 DPRINTF(Decode, "[tid:%i]: Squashing.\n",tid);
313
314 if (decodeStatus[tid] == Blocked ||
315 decodeStatus[tid] == Unblocking) {
316#if !FULL_SYSTEM
317 // In syscall emulation, we can have both a block and a squash due
318 // to a syscall in the same cycle. This would cause both signals to
319 // be high. This shouldn't happen in full system.
320 // @todo: Determine if this still happens.
321 if (toFetch->decodeBlock[tid]) {
322 toFetch->decodeBlock[tid] = 0;
323 } else {
324 toFetch->decodeUnblock[tid] = 1;
325 }
326#else
327 toFetch->decodeUnblock[tid] = 1;
328#endif
329 }
330
210 DPRINTF(Decode, "Decode: Squashing.\n");
331 // Set status to squashing.
211 // Set status to squashing.
332 decodeStatus[tid] = Squashing;
212 _status = Squashing;
333
213
334 // Go through incoming instructions from fetch and squash them.
335 unsigned squash_count = 0;
214 // Maybe advance the time buffer? Not sure what to do in the normal
215 // case.
336
216
337 for (int i=0; i<fromFetch->size; i++) {
338 if (fromFetch->insts[i]->threadNumber == tid) {
339 fromFetch->insts[i]->squashed = true;
340 squash_count++;
341 }
342 }
343
344 while (!insts[tid].empty()) {
345 insts[tid].pop();
346 }
347
348 // Clear the skid buffer in case it has any data in it.
217 // Clear the skid buffer in case it has any data in it.
349 while (!skidBuffer[tid].empty()) {
350 skidBuffer[tid].pop();
218 while (!skidBuffer.empty())
219 {
220 skidBuffer.pop();
351 }
221 }
352
353 return squash_count;
354}
355
356template<class Impl>
357void
222}
223
224template<class Impl>
225void
358DefaultDecode<Impl>::skidInsert(unsigned tid)
226SimpleDecode<Impl>::tick()
359{
227{
360 DynInstPtr inst = NULL;
228 // Decode should try to execute as many instructions as its bandwidth
229 // will allow, as long as it is not currently blocked.
230 if (_status != Blocked && _status != Squashing) {
231 DPRINTF(Decode, "Decode: Not blocked, so attempting to run "
232 "stage.\n");
233 // Make sure that the skid buffer has something in it if the
234 // status is unblocking.
235 assert(_status == Unblocking ? !skidBuffer.empty() : 1);
361
236
362 while (!insts[tid].empty()) {
363 inst = insts[tid].front();
237 decode();
364
238
365 insts[tid].pop();
239 // If the status was unblocking, then instructions from the skid
240 // buffer were used. Remove those instructions and handle
241 // the rest of unblocking.
242 if (_status == Unblocking) {
243 ++decodeUnblockCycles;
366
244
367 assert(tid == inst->threadNumber);
245 if (fetchInstsValid()) {
246 // Add the current inputs to the skid buffer so they can be
247 // reprocessed when this stage unblocks.
248 skidBuffer.push(*fromFetch);
249 }
368
250
369 DPRINTF(Decode,"Inserting [sn:%lli] PC:%#x into decode skidBuffer %i\n",
370 inst->seqNum, inst->readPC(), inst->threadNumber);
251 unblock();
252 }
253 } else if (_status == Blocked) {
254 ++decodeBlockedCycles;
371
255
372 skidBuffer[tid].push(inst);
373 }
256 if (fetchInstsValid()) {
257 block();
258 }
374
259
375 // @todo: Eventually need to enforce this by not letting a thread
376 // fetch past its skidbuffer
377 assert(skidBuffer[tid].size() <= skidBufferMax);
378}
260 if (!fromRename->renameInfo.stall &&
261 !fromIEW->iewInfo.stall &&
262 !fromCommit->commitInfo.stall) {
263 DPRINTF(Decode, "Decode: Stall signals cleared, going to "
264 "unblock.\n");
265 _status = Unblocking;
379
266
380template<class Impl>
381bool
382DefaultDecode<Impl>::skidsEmpty()
383{
384 list<unsigned>::iterator threads = (*activeThreads).begin();
385
386 while (threads != (*activeThreads).end()) {
387 if (!skidBuffer[*threads++].empty())
388 return false;
389 }
390
391 return true;
392}
393
394template<class Impl>
395void
396DefaultDecode<Impl>::updateStatus()
397{
398 bool any_unblocking = false;
399
400 list<unsigned>::iterator threads = (*activeThreads).begin();
401
402 threads = (*activeThreads).begin();
403
404 while (threads != (*activeThreads).end()) {
405 unsigned tid = *threads++;
406
407 if (decodeStatus[tid] == Unblocking) {
408 any_unblocking = true;
409 break;
267 // Continue to tell previous stage to block until this
268 // stage is done unblocking.
269 toFetch->decodeInfo.stall = true;
270 } else {
271 DPRINTF(Decode, "Decode: Still blocked.\n");
272 toFetch->decodeInfo.stall = true;
410 }
273 }
411 }
412
274
413 // Decode will have activity if it's unblocking.
414 if (any_unblocking) {
415 if (_status == Inactive) {
416 _status = Active;
417
418 DPRINTF(Activity, "Activating stage.\n");
419
420 cpu->activateStage(FullCPU::DecodeIdx);
275 if (fromCommit->commitInfo.squash ||
276 fromCommit->commitInfo.robSquashing) {
277 squash();
421 }
278 }
422 } else {
423 // If it's not unblocking, then decode will not have any internal
424 // activity. Switch it to inactive.
425 if (_status == Active) {
426 _status = Inactive;
427 DPRINTF(Activity, "Deactivating stage.\n");
279 } else if (_status == Squashing) {
280 if (!fromCommit->commitInfo.squash &&
281 !fromCommit->commitInfo.robSquashing) {
282 _status = Running;
283 } else if (fromCommit->commitInfo.squash) {
284 ++decodeSquashCycles;
428
285
429 cpu->deactivateStage(FullCPU::DecodeIdx);
286 squash();
430 }
431 }
432}
433
287 }
288 }
289}
290
434template <class Impl>
435void
436DefaultDecode<Impl>::sortInsts()
437{
438 int insts_from_fetch = fromFetch->size;
439#ifdef DEBUG
440 for (int i=0; i < numThreads; i++)
441 assert(insts[i].empty());
442#endif
443 for (int i = 0; i < insts_from_fetch; ++i) {
444 insts[fromFetch->insts[i]->threadNumber].push(fromFetch->insts[i]);
445 }
446}
447
448template<class Impl>
449void
291template<class Impl>
292void
450DefaultDecode<Impl>::readStallSignals(unsigned tid)
293SimpleDecode<Impl>::decode()
451{
294{
452 if (fromRename->renameBlock[tid]) {
453 stalls[tid].rename = true;
295 // Check time buffer if being told to squash.
296 if (fromCommit->commitInfo.squash) {
297 squash();
298 return;
454 }
455
299 }
300
456 if (fromRename->renameUnblock[tid]) {
457 assert(stalls[tid].rename);
458 stalls[tid].rename = false;
301 // Check time buffer if being told to stall.
302 if (fromRename->renameInfo.stall ||
303 fromIEW->iewInfo.stall ||
304 fromCommit->commitInfo.stall) {
305 block();
306 return;
459 }
460
307 }
308
461 if (fromIEW->iewBlock[tid]) {
462 stalls[tid].iew = true;
463 }
464
465 if (fromIEW->iewUnblock[tid]) {
466 assert(stalls[tid].iew);
467 stalls[tid].iew = false;
468 }
469
470 if (fromCommit->commitBlock[tid]) {
471 stalls[tid].commit = true;
472 }
473
474 if (fromCommit->commitUnblock[tid]) {
475 assert(stalls[tid].commit);
476 stalls[tid].commit = false;
477 }
478}
479
480template <class Impl>
481bool
482DefaultDecode<Impl>::checkSignalsAndUpdate(unsigned tid)
483{
484 // Check if there's a squash signal, squash if there is.
485 // Check stall signals, block if necessary.
486 // If status was blocked
487 // Check if stall conditions have passed
488 // if so then go to unblocking
489 // If status was Squashing
490 // check if squashing is not high. Switch to running this cycle.
491
492 // Update the per thread stall statuses.
493 readStallSignals(tid);
494
495 // Check squash signals from commit.
496 if (fromCommit->commitInfo[tid].squash) {
497
498 DPRINTF(Decode, "[tid:%u]: Squashing instructions due to squash "
499 "from commit.\n", tid);
500
501 squash(tid);
502
503 return true;
504 }
505
506 // Check ROB squash signals from commit.
507 if (fromCommit->commitInfo[tid].robSquashing) {
508 DPRINTF(Decode, "[tid:%]: ROB is still squashing.\n",tid);
509
510 // Continue to squash.
511 decodeStatus[tid] = Squashing;
512
513 return true;
514 }
515
516 if (checkStall(tid)) {
517 return block(tid);
518 }
519
520 if (decodeStatus[tid] == Blocked) {
521 DPRINTF(Decode, "[tid:%u]: Done blocking, switching to unblocking.\n",
522 tid);
523
524 decodeStatus[tid] = Unblocking;
525
526 unblock(tid);
527
528 return true;
529 }
530
531 if (decodeStatus[tid] == Squashing) {
532 // Switch status to running if decode isn't being told to block or
533 // squash this cycle.
534 DPRINTF(Decode, "[tid:%u]: Done squashing, switching to running.\n",
535 tid);
536
537 decodeStatus[tid] = Running;
538
539 return false;
540 }
541
542 // If we've reached this point, we have not gotten any signals that
543 // cause decode to change its status. Decode remains the same as before.
544 return false;
545}
546
547template<class Impl>
548void
549DefaultDecode<Impl>::tick()
550{
551 wroteToTimeBuffer = false;
552
553 bool status_change = false;
554
555 toRenameIndex = 0;
556
557 list<unsigned>::iterator threads = (*activeThreads).begin();
558
559 sortInsts();
560
561 //Check stall and squash signals.
562 while (threads != (*activeThreads).end()) {
563 unsigned tid = *threads++;
564
565 DPRINTF(Decode,"Processing [tid:%i]\n",tid);
566 status_change = checkSignalsAndUpdate(tid) || status_change;
567
568 decode(status_change, tid);
569 }
570
571 if (status_change) {
572 updateStatus();
573 }
574
575 if (wroteToTimeBuffer) {
576 DPRINTF(Activity, "Activity this cycle.\n");
577
578 cpu->activityThisCycle();
579 }
580}
581
582template<class Impl>
583void
584DefaultDecode<Impl>::decode(bool &status_change, unsigned tid)
585{
586 // If status is Running or idle,
587 // call decodeInsts()
588 // If status is Unblocking,
589 // buffer any instructions coming from fetch
590 // continue trying to empty skid buffer
591 // check if stall conditions have passed
592
593 if (decodeStatus[tid] == Blocked) {
594 ++decodeBlockedCycles;
595 } else if (decodeStatus[tid] == Squashing) {
596 ++decodeSquashCycles;
597 }
598
599 // Decode should try to decode as many instructions as its bandwidth
600 // will allow, as long as it is not currently blocked.
601 if (decodeStatus[tid] == Running ||
602 decodeStatus[tid] == Idle) {
603 DPRINTF(Decode, "[tid:%u] Not blocked, so attempting to run "
604 "stage.\n",tid);
605
606 decodeInsts(tid);
607 } else if (decodeStatus[tid] == Unblocking) {
608 // Make sure that the skid buffer has something in it if the
609 // status is unblocking.
610 assert(!skidsEmpty());
611
612 // If the status was unblocking, then instructions from the skid
613 // buffer were used. Remove those instructions and handle
614 // the rest of unblocking.
615 decodeInsts(tid);
616
617 if (fetchInstsValid()) {
618 // Add the current inputs to the skid buffer so they can be
619 // reprocessed when this stage unblocks.
620 skidInsert(tid);
621 }
622
623 status_change = unblock(tid) || status_change;
624 }
625}
626
627template <class Impl>
628void
629DefaultDecode<Impl>::decodeInsts(unsigned tid)
630{
631 // Instructions can come either from the skid buffer or the list of
632 // instructions coming from fetch, depending on decode's status.
633 int insts_available = decodeStatus[tid] == Unblocking ?
634 skidBuffer[tid].size() : insts[tid].size();
635
636 if (insts_available == 0) {
637 DPRINTF(Decode, "[tid:%u] Nothing to do, breaking out"
638 " early.\n",tid);
309 // Check fetch queue to see if instructions are available.
310 // If no available instructions, do nothing, unless this stage is
311 // currently unblocking.
312 if (!fetchInstsValid() && _status != Unblocking) {
313 DPRINTF(Decode, "Decode: Nothing to do, breaking out early.\n");
639 // Should I change the status to idle?
640 ++decodeIdleCycles;
641 return;
314 // Should I change the status to idle?
315 ++decodeIdleCycles;
316 return;
642 } else if (decodeStatus[tid] == Unblocking) {
643 DPRINTF(Decode, "[tid:%u] Unblocking, removing insts from skid "
644 "buffer.\n",tid);
645 ++decodeUnblockCycles;
646 } else if (decodeStatus[tid] == Running) {
647 ++decodeRunCycles;
648 }
649
317 }
318
319 // Might be better to use a base DynInst * instead?
650 DynInstPtr inst;
651
320 DynInstPtr inst;
321
652 std::queue<DynInstPtr>
653 &insts_to_decode = decodeStatus[tid] == Unblocking ?
654 skidBuffer[tid] : insts[tid];
322 unsigned to_rename_index = 0;
655
323
656 DPRINTF(Decode, "[tid:%u]: Sending instruction to rename.\n",tid);
324 int insts_available = _status == Unblocking ?
325 skidBuffer.front().size - numInst :
326 fromFetch->size;
657
327
658 while (insts_available > 0 && toRenameIndex < decodeWidth) {
659 assert(!insts_to_decode.empty());
328 // Debug block...
329#if 0
330 if (insts_available) {
331 DPRINTF(Decode, "Decode: Instructions available.\n");
332 } else {
333 if (_status == Unblocking && skidBuffer.empty()) {
334 DPRINTF(Decode, "Decode: No instructions available, skid buffer "
335 "empty.\n");
336 } else if (_status != Unblocking &&
337 !fromFetch->insts[0]) {
338 DPRINTF(Decode, "Decode: No instructions available, fetch queue "
339 "empty.\n");
340 } else {
341 panic("Decode: No instructions available, unexpected condition!"
342 "\n");
343 }
344 }
345#endif
660
346
661 inst = insts_to_decode.front();
347 while (insts_available > 0)
348 {
349 DPRINTF(Decode, "Decode: Sending instruction to rename.\n");
662
350
663 insts_to_decode.pop();
351 inst = _status == Unblocking ? skidBuffer.front().insts[numInst] :
352 fromFetch->insts[numInst];
664
353
665 DPRINTF(Decode, "[tid:%u]: Processing instruction [sn:%lli] with "
666 "PC %#x\n",
667 tid, inst->seqNum, inst->readPC());
354 DPRINTF(Decode, "Decode: Processing instruction %i with PC %#x\n",
355 inst->seqNum, inst->readPC());
668
669 if (inst->isSquashed()) {
356
357 if (inst->isSquashed()) {
670 DPRINTF(Decode, "[tid:%u]: Instruction %i with PC %#x is "
358 DPRINTF(Decode, "Decode: Instruction %i with PC %#x is "
671 "squashed, skipping.\n",
359 "squashed, skipping.\n",
672 tid, inst->seqNum, inst->readPC());
360 inst->seqNum, inst->readPC());
673
674 ++decodeSquashedInsts;
675
361
362 ++decodeSquashedInsts;
363
364 ++numInst;
676 --insts_available;
677
678 continue;
679 }
680
365 --insts_available;
366
367 continue;
368 }
369
370
681 // Also check if instructions have no source registers. Mark
682 // them as ready to issue at any time. Not sure if this check
683 // should exist here or at a later stage; however it doesn't matter
684 // too much for function correctness.
371 // Also check if instructions have no source registers. Mark
372 // them as ready to issue at any time. Not sure if this check
373 // should exist here or at a later stage; however it doesn't matter
374 // too much for function correctness.
375 // Isn't this handled by the inst queue?
685 if (inst->numSrcRegs() == 0) {
686 inst->setCanIssue();
687 }
688
689 // This current instruction is valid, so add it into the decode
690 // queue. The next instruction may not be valid, so check to
691 // see if branches were predicted correctly.
376 if (inst->numSrcRegs() == 0) {
377 inst->setCanIssue();
378 }
379
380 // This current instruction is valid, so add it into the decode
381 // queue. The next instruction may not be valid, so check to
382 // see if branches were predicted correctly.
692 toRename->insts[toRenameIndex] = inst;
383 toRename->insts[to_rename_index] = inst;
693
694 ++(toRename->size);
384
385 ++(toRename->size);
695 ++toRenameIndex;
696 ++decodeDecodedInsts;
697 --insts_available;
698
699 // Ensure that if it was predicted as a branch, it really is a
700 // branch.
701 if (inst->predTaken() && !inst->isControl()) {
702 panic("Instruction predicted as a branch!");
703
704 ++decodeControlMispred;
386
387 // Ensure that if it was predicted as a branch, it really is a
388 // branch.
389 if (inst->predTaken() && !inst->isControl()) {
390 panic("Instruction predicted as a branch!");
391
392 ++decodeControlMispred;
705
706 // Might want to set some sort of boolean and just do
707 // a check at the end
393 // Might want to set some sort of boolean and just do
394 // a check at the end
708 squash(inst, inst->threadNumber);
709
395 squash(inst);
710 break;
711 }
712
713 // Go ahead and compute any PC-relative branches.
396 break;
397 }
398
399 // Go ahead and compute any PC-relative branches.
400
714 if (inst->isDirectCtrl() && inst->isUncondCtrl()) {
401 if (inst->isDirectCtrl() && inst->isUncondCtrl()) {
715 ++decodeBranchResolved;
402
716 inst->setNextPC(inst->branchTarget());
717
718 if (inst->mispredicted()) {
719 ++decodeBranchMispred;
403 inst->setNextPC(inst->branchTarget());
404
405 if (inst->mispredicted()) {
406 ++decodeBranchMispred;
720
721 // Might want to set some sort of boolean and just do
722 // a check at the end
407 // Might want to set some sort of boolean and just do
408 // a check at the end
723 squash(inst, inst->threadNumber);
724
409 squash(inst);
725 break;
726 }
727 }
410 break;
411 }
412 }
728 }
729
413
730 // If we didn't process all instructions, then we will need to block
731 // and put all those instructions into the skid buffer.
732 if (!insts_to_decode.empty()) {
733 block(tid);
734 }
414 // Normally can check if a direct branch has the right target
415 // addr (either the immediate, or the branch PC + 4) and redirect
416 // fetch if it's incorrect.
735
417
736 // Record that decode has written to the time buffer for activity
737 // tracking.
738 if (toRenameIndex) {
739 wroteToTimeBuffer = true;
418 // Increment which instruction we're looking at.
419 ++numInst;
420 ++to_rename_index;
421 ++decodeDecodedInsts;
422
423 --insts_available;
740 }
424 }
425
426 numInst = 0;
741}
427}