rename_impl.hh (9444:ab47fe7f03f0) rename_impl.hh (9527:68154bc0e0ea)
1/*
2 * Copyright (c) 2010-2012 ARM Limited
3 * All rights reserved.
4 *
5 * The license below extends only to copyright in the software and shall
6 * not be construed as granting a license to any other intellectual
7 * property including but not limited to intellectual property relating
8 * to a hardware implementation of the functionality of the software
9 * licensed hereunder. You may use the software subject to the license
10 * terms below provided that you ensure that this notice is replicated
11 * unmodified and in its entirety in all distributions of the software,
12 * modified or unmodified, in source code or in binary form.
13 *
14 * Copyright (c) 2004-2006 The Regents of The University of Michigan
15 * All rights reserved.
16 *
17 * Redistribution and use in source and binary forms, with or without
18 * modification, are permitted provided that the following conditions are
19 * met: redistributions of source code must retain the above copyright
20 * notice, this list of conditions and the following disclaimer;
21 * redistributions in binary form must reproduce the above copyright
22 * notice, this list of conditions and the following disclaimer in the
23 * documentation and/or other materials provided with the distribution;
24 * neither the name of the copyright holders nor the names of its
25 * contributors may be used to endorse or promote products derived from
26 * this software without specific prior written permission.
27 *
28 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
29 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
30 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
31 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
32 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
33 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
34 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
35 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
36 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
37 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
38 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
39 *
40 * Authors: Kevin Lim
41 * Korey Sewell
42 */
43
44#include <list>
45
46#include "arch/isa_traits.hh"
47#include "arch/registers.hh"
48#include "config/the_isa.hh"
49#include "cpu/o3/rename.hh"
50#include "debug/Activity.hh"
51#include "debug/Rename.hh"
1/*
2 * Copyright (c) 2010-2012 ARM Limited
3 * All rights reserved.
4 *
5 * The license below extends only to copyright in the software and shall
6 * not be construed as granting a license to any other intellectual
7 * property including but not limited to intellectual property relating
8 * to a hardware implementation of the functionality of the software
9 * licensed hereunder. You may use the software subject to the license
10 * terms below provided that you ensure that this notice is replicated
11 * unmodified and in its entirety in all distributions of the software,
12 * modified or unmodified, in source code or in binary form.
13 *
14 * Copyright (c) 2004-2006 The Regents of The University of Michigan
15 * All rights reserved.
16 *
17 * Redistribution and use in source and binary forms, with or without
18 * modification, are permitted provided that the following conditions are
19 * met: redistributions of source code must retain the above copyright
20 * notice, this list of conditions and the following disclaimer;
21 * redistributions in binary form must reproduce the above copyright
22 * notice, this list of conditions and the following disclaimer in the
23 * documentation and/or other materials provided with the distribution;
24 * neither the name of the copyright holders nor the names of its
25 * contributors may be used to endorse or promote products derived from
26 * this software without specific prior written permission.
27 *
28 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
29 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
30 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
31 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
32 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
33 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
34 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
35 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
36 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
37 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
38 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
39 *
40 * Authors: Kevin Lim
41 * Korey Sewell
42 */
43
44#include <list>
45
46#include "arch/isa_traits.hh"
47#include "arch/registers.hh"
48#include "config/the_isa.hh"
49#include "cpu/o3/rename.hh"
50#include "debug/Activity.hh"
51#include "debug/Rename.hh"
52#include "debug/O3PipeView.hh"
52#include "params/DerivO3CPU.hh"
53
54using namespace std;
55
56template <class Impl>
57DefaultRename<Impl>::DefaultRename(O3CPU *_cpu, DerivO3CPUParams *params)
58 : cpu(_cpu),
59 iewToRenameDelay(params->iewToRenameDelay),
60 decodeToRenameDelay(params->decodeToRenameDelay),
61 commitToRenameDelay(params->commitToRenameDelay),
62 renameWidth(params->renameWidth),
63 commitWidth(params->commitWidth),
64 numThreads(params->numThreads),
65 maxPhysicalRegs(params->numPhysIntRegs + params->numPhysFloatRegs)
66{
67 // @todo: Make into a parameter.
68 skidBufferMax = (2 * (decodeToRenameDelay * params->decodeWidth)) + renameWidth;
69}
70
71template <class Impl>
72std::string
73DefaultRename<Impl>::name() const
74{
75 return cpu->name() + ".rename";
76}
77
78template <class Impl>
79void
80DefaultRename<Impl>::regStats()
81{
82 renameSquashCycles
83 .name(name() + ".SquashCycles")
84 .desc("Number of cycles rename is squashing")
85 .prereq(renameSquashCycles);
86 renameIdleCycles
87 .name(name() + ".IdleCycles")
88 .desc("Number of cycles rename is idle")
89 .prereq(renameIdleCycles);
90 renameBlockCycles
91 .name(name() + ".BlockCycles")
92 .desc("Number of cycles rename is blocking")
93 .prereq(renameBlockCycles);
94 renameSerializeStallCycles
95 .name(name() + ".serializeStallCycles")
96 .desc("count of cycles rename stalled for serializing inst")
97 .flags(Stats::total);
98 renameRunCycles
99 .name(name() + ".RunCycles")
100 .desc("Number of cycles rename is running")
101 .prereq(renameIdleCycles);
102 renameUnblockCycles
103 .name(name() + ".UnblockCycles")
104 .desc("Number of cycles rename is unblocking")
105 .prereq(renameUnblockCycles);
106 renameRenamedInsts
107 .name(name() + ".RenamedInsts")
108 .desc("Number of instructions processed by rename")
109 .prereq(renameRenamedInsts);
110 renameSquashedInsts
111 .name(name() + ".SquashedInsts")
112 .desc("Number of squashed instructions processed by rename")
113 .prereq(renameSquashedInsts);
114 renameROBFullEvents
115 .name(name() + ".ROBFullEvents")
116 .desc("Number of times rename has blocked due to ROB full")
117 .prereq(renameROBFullEvents);
118 renameIQFullEvents
119 .name(name() + ".IQFullEvents")
120 .desc("Number of times rename has blocked due to IQ full")
121 .prereq(renameIQFullEvents);
122 renameLSQFullEvents
123 .name(name() + ".LSQFullEvents")
124 .desc("Number of times rename has blocked due to LSQ full")
125 .prereq(renameLSQFullEvents);
126 renameFullRegistersEvents
127 .name(name() + ".FullRegisterEvents")
128 .desc("Number of times there has been no free registers")
129 .prereq(renameFullRegistersEvents);
130 renameRenamedOperands
131 .name(name() + ".RenamedOperands")
132 .desc("Number of destination operands rename has renamed")
133 .prereq(renameRenamedOperands);
134 renameRenameLookups
135 .name(name() + ".RenameLookups")
136 .desc("Number of register rename lookups that rename has made")
137 .prereq(renameRenameLookups);
138 renameCommittedMaps
139 .name(name() + ".CommittedMaps")
140 .desc("Number of HB maps that are committed")
141 .prereq(renameCommittedMaps);
142 renameUndoneMaps
143 .name(name() + ".UndoneMaps")
144 .desc("Number of HB maps that are undone due to squashing")
145 .prereq(renameUndoneMaps);
146 renamedSerializing
147 .name(name() + ".serializingInsts")
148 .desc("count of serializing insts renamed")
149 .flags(Stats::total)
150 ;
151 renamedTempSerializing
152 .name(name() + ".tempSerializingInsts")
153 .desc("count of temporary serializing insts renamed")
154 .flags(Stats::total)
155 ;
156 renameSkidInsts
157 .name(name() + ".skidInsts")
158 .desc("count of insts added to the skid buffer")
159 .flags(Stats::total)
160 ;
161 intRenameLookups
162 .name(name() + ".int_rename_lookups")
163 .desc("Number of integer rename lookups")
164 .prereq(intRenameLookups);
165 fpRenameLookups
166 .name(name() + ".fp_rename_lookups")
167 .desc("Number of floating rename lookups")
168 .prereq(fpRenameLookups);
169}
170
171template <class Impl>
172void
173DefaultRename<Impl>::setTimeBuffer(TimeBuffer<TimeStruct> *tb_ptr)
174{
175 timeBuffer = tb_ptr;
176
177 // Setup wire to read information from time buffer, from IEW stage.
178 fromIEW = timeBuffer->getWire(-iewToRenameDelay);
179
180 // Setup wire to read infromation from time buffer, from commit stage.
181 fromCommit = timeBuffer->getWire(-commitToRenameDelay);
182
183 // Setup wire to write information to previous stages.
184 toDecode = timeBuffer->getWire(0);
185}
186
187template <class Impl>
188void
189DefaultRename<Impl>::setRenameQueue(TimeBuffer<RenameStruct> *rq_ptr)
190{
191 renameQueue = rq_ptr;
192
193 // Setup wire to write information to future stages.
194 toIEW = renameQueue->getWire(0);
195}
196
197template <class Impl>
198void
199DefaultRename<Impl>::setDecodeQueue(TimeBuffer<DecodeStruct> *dq_ptr)
200{
201 decodeQueue = dq_ptr;
202
203 // Setup wire to get information from decode.
204 fromDecode = decodeQueue->getWire(-decodeToRenameDelay);
205}
206
207template <class Impl>
208void
209DefaultRename<Impl>::startupStage()
210{
211 resetStage();
212}
213
214template <class Impl>
215void
216DefaultRename<Impl>::resetStage()
217{
218 _status = Inactive;
219
220 resumeSerialize = false;
221 resumeUnblocking = false;
222
223 // Grab the number of free entries directly from the stages.
224 for (ThreadID tid = 0; tid < numThreads; tid++) {
225 renameStatus[tid] = Idle;
226
227 freeEntries[tid].iqEntries = iew_ptr->instQueue.numFreeEntries(tid);
228 freeEntries[tid].lsqEntries = iew_ptr->ldstQueue.numFreeEntries(tid);
229 freeEntries[tid].robEntries = commit_ptr->numROBFreeEntries(tid);
230 emptyROB[tid] = true;
231
232 stalls[tid].iew = false;
233 stalls[tid].commit = false;
234 serializeInst[tid] = NULL;
235
236 instsInProgress[tid] = 0;
237
238 serializeOnNextInst[tid] = false;
239 }
240}
241
242template<class Impl>
243void
244DefaultRename<Impl>::setActiveThreads(list<ThreadID> *at_ptr)
245{
246 activeThreads = at_ptr;
247}
248
249
250template <class Impl>
251void
252DefaultRename<Impl>::setRenameMap(RenameMap rm_ptr[])
253{
254 for (ThreadID tid = 0; tid < numThreads; tid++)
255 renameMap[tid] = &rm_ptr[tid];
256}
257
258template <class Impl>
259void
260DefaultRename<Impl>::setFreeList(FreeList *fl_ptr)
261{
262 freeList = fl_ptr;
263}
264
265template<class Impl>
266void
267DefaultRename<Impl>::setScoreboard(Scoreboard *_scoreboard)
268{
269 scoreboard = _scoreboard;
270}
271
272template <class Impl>
273bool
274DefaultRename<Impl>::isDrained() const
275{
276 for (ThreadID tid = 0; tid < numThreads; tid++) {
277 if (instsInProgress[tid] != 0 ||
278 !historyBuffer[tid].empty() ||
279 !skidBuffer[tid].empty() ||
280 !insts[tid].empty())
281 return false;
282 }
283 return true;
284}
285
286template <class Impl>
287void
288DefaultRename<Impl>::takeOverFrom()
289{
290 resetStage();
291}
292
293template <class Impl>
294void
295DefaultRename<Impl>::drainSanityCheck() const
296{
297 for (ThreadID tid = 0; tid < numThreads; tid++) {
298 assert(historyBuffer[tid].empty());
299 assert(insts[tid].empty());
300 assert(skidBuffer[tid].empty());
301 assert(instsInProgress[tid] == 0);
302 }
303}
304
305template <class Impl>
306void
307DefaultRename<Impl>::squash(const InstSeqNum &squash_seq_num, ThreadID tid)
308{
309 DPRINTF(Rename, "[tid:%u]: Squashing instructions.\n",tid);
310
311 // Clear the stall signal if rename was blocked or unblocking before.
312 // If it still needs to block, the blocking should happen the next
313 // cycle and there should be space to hold everything due to the squash.
314 if (renameStatus[tid] == Blocked ||
315 renameStatus[tid] == Unblocking) {
316 toDecode->renameUnblock[tid] = 1;
317
318 resumeSerialize = false;
319 serializeInst[tid] = NULL;
320 } else if (renameStatus[tid] == SerializeStall) {
321 if (serializeInst[tid]->seqNum <= squash_seq_num) {
322 DPRINTF(Rename, "Rename will resume serializing after squash\n");
323 resumeSerialize = true;
324 assert(serializeInst[tid]);
325 } else {
326 resumeSerialize = false;
327 toDecode->renameUnblock[tid] = 1;
328
329 serializeInst[tid] = NULL;
330 }
331 }
332
333 // Set the status to Squashing.
334 renameStatus[tid] = Squashing;
335
336 // Squash any instructions from decode.
337 unsigned squashCount = 0;
338
339 for (int i=0; i<fromDecode->size; i++) {
340 if (fromDecode->insts[i]->threadNumber == tid &&
341 fromDecode->insts[i]->seqNum > squash_seq_num) {
342 fromDecode->insts[i]->setSquashed();
343 wroteToTimeBuffer = true;
344 squashCount++;
345 }
346
347 }
348
349 // Clear the instruction list and skid buffer in case they have any
350 // insts in them.
351 insts[tid].clear();
352
353 // Clear the skid buffer in case it has any data in it.
354 skidBuffer[tid].clear();
355
356 doSquash(squash_seq_num, tid);
357}
358
359template <class Impl>
360void
361DefaultRename<Impl>::tick()
362{
363 wroteToTimeBuffer = false;
364
365 blockThisCycle = false;
366
367 bool status_change = false;
368
369 toIEWIndex = 0;
370
371 sortInsts();
372
373 list<ThreadID>::iterator threads = activeThreads->begin();
374 list<ThreadID>::iterator end = activeThreads->end();
375
376 // Check stall and squash signals.
377 while (threads != end) {
378 ThreadID tid = *threads++;
379
380 DPRINTF(Rename, "Processing [tid:%i]\n", tid);
381
382 status_change = checkSignalsAndUpdate(tid) || status_change;
383
384 rename(status_change, tid);
385 }
386
387 if (status_change) {
388 updateStatus();
389 }
390
391 if (wroteToTimeBuffer) {
392 DPRINTF(Activity, "Activity this cycle.\n");
393 cpu->activityThisCycle();
394 }
395
396 threads = activeThreads->begin();
397
398 while (threads != end) {
399 ThreadID tid = *threads++;
400
401 // If we committed this cycle then doneSeqNum will be > 0
402 if (fromCommit->commitInfo[tid].doneSeqNum != 0 &&
403 !fromCommit->commitInfo[tid].squash &&
404 renameStatus[tid] != Squashing) {
405
406 removeFromHistory(fromCommit->commitInfo[tid].doneSeqNum,
407 tid);
408 }
409 }
410
411 // @todo: make into updateProgress function
412 for (ThreadID tid = 0; tid < numThreads; tid++) {
413 instsInProgress[tid] -= fromIEW->iewInfo[tid].dispatched;
414
415 assert(instsInProgress[tid] >=0);
416 }
417
418}
419
420template<class Impl>
421void
422DefaultRename<Impl>::rename(bool &status_change, ThreadID tid)
423{
424 // If status is Running or idle,
425 // call renameInsts()
426 // If status is Unblocking,
427 // buffer any instructions coming from decode
428 // continue trying to empty skid buffer
429 // check if stall conditions have passed
430
431 if (renameStatus[tid] == Blocked) {
432 ++renameBlockCycles;
433 } else if (renameStatus[tid] == Squashing) {
434 ++renameSquashCycles;
435 } else if (renameStatus[tid] == SerializeStall) {
436 ++renameSerializeStallCycles;
437 // If we are currently in SerializeStall and resumeSerialize
438 // was set, then that means that we are resuming serializing
439 // this cycle. Tell the previous stages to block.
440 if (resumeSerialize) {
441 resumeSerialize = false;
442 block(tid);
443 toDecode->renameUnblock[tid] = false;
444 }
445 } else if (renameStatus[tid] == Unblocking) {
446 if (resumeUnblocking) {
447 block(tid);
448 resumeUnblocking = false;
449 toDecode->renameUnblock[tid] = false;
450 }
451 }
452
453 if (renameStatus[tid] == Running ||
454 renameStatus[tid] == Idle) {
455 DPRINTF(Rename, "[tid:%u]: Not blocked, so attempting to run "
456 "stage.\n", tid);
457
458 renameInsts(tid);
459 } else if (renameStatus[tid] == Unblocking) {
460 renameInsts(tid);
461
462 if (validInsts()) {
463 // Add the current inputs to the skid buffer so they can be
464 // reprocessed when this stage unblocks.
465 skidInsert(tid);
466 }
467
468 // If we switched over to blocking, then there's a potential for
469 // an overall status change.
470 status_change = unblock(tid) || status_change || blockThisCycle;
471 }
472}
473
474template <class Impl>
475void
476DefaultRename<Impl>::renameInsts(ThreadID tid)
477{
478 // Instructions can be either in the skid buffer or the queue of
479 // instructions coming from decode, depending on the status.
480 int insts_available = renameStatus[tid] == Unblocking ?
481 skidBuffer[tid].size() : insts[tid].size();
482
483 // Check the decode queue to see if instructions are available.
484 // If there are no available instructions to rename, then do nothing.
485 if (insts_available == 0) {
486 DPRINTF(Rename, "[tid:%u]: Nothing to do, breaking out early.\n",
487 tid);
488 // Should I change status to idle?
489 ++renameIdleCycles;
490 return;
491 } else if (renameStatus[tid] == Unblocking) {
492 ++renameUnblockCycles;
493 } else if (renameStatus[tid] == Running) {
494 ++renameRunCycles;
495 }
496
497 DynInstPtr inst;
498
499 // Will have to do a different calculation for the number of free
500 // entries.
501 int free_rob_entries = calcFreeROBEntries(tid);
502 int free_iq_entries = calcFreeIQEntries(tid);
503 int free_lsq_entries = calcFreeLSQEntries(tid);
504 int min_free_entries = free_rob_entries;
505
506 FullSource source = ROB;
507
508 if (free_iq_entries < min_free_entries) {
509 min_free_entries = free_iq_entries;
510 source = IQ;
511 }
512
513 if (free_lsq_entries < min_free_entries) {
514 min_free_entries = free_lsq_entries;
515 source = LSQ;
516 }
517
518 // Check if there's any space left.
519 if (min_free_entries <= 0) {
520 DPRINTF(Rename, "[tid:%u]: Blocking due to no free ROB/IQ/LSQ "
521 "entries.\n"
522 "ROB has %i free entries.\n"
523 "IQ has %i free entries.\n"
524 "LSQ has %i free entries.\n",
525 tid,
526 free_rob_entries,
527 free_iq_entries,
528 free_lsq_entries);
529
530 blockThisCycle = true;
531
532 block(tid);
533
534 incrFullStat(source);
535
536 return;
537 } else if (min_free_entries < insts_available) {
538 DPRINTF(Rename, "[tid:%u]: Will have to block this cycle."
539 "%i insts available, but only %i insts can be "
540 "renamed due to ROB/IQ/LSQ limits.\n",
541 tid, insts_available, min_free_entries);
542
543 insts_available = min_free_entries;
544
545 blockThisCycle = true;
546
547 incrFullStat(source);
548 }
549
550 InstQueue &insts_to_rename = renameStatus[tid] == Unblocking ?
551 skidBuffer[tid] : insts[tid];
552
553 DPRINTF(Rename, "[tid:%u]: %i available instructions to "
554 "send iew.\n", tid, insts_available);
555
556 DPRINTF(Rename, "[tid:%u]: %i insts pipelining from Rename | %i insts "
557 "dispatched to IQ last cycle.\n",
558 tid, instsInProgress[tid], fromIEW->iewInfo[tid].dispatched);
559
560 // Handle serializing the next instruction if necessary.
561 if (serializeOnNextInst[tid]) {
562 if (emptyROB[tid] && instsInProgress[tid] == 0) {
563 // ROB already empty; no need to serialize.
564 serializeOnNextInst[tid] = false;
565 } else if (!insts_to_rename.empty()) {
566 insts_to_rename.front()->setSerializeBefore();
567 }
568 }
569
570 int renamed_insts = 0;
571
572 while (insts_available > 0 && toIEWIndex < renameWidth) {
573 DPRINTF(Rename, "[tid:%u]: Sending instructions to IEW.\n", tid);
574
575 assert(!insts_to_rename.empty());
576
577 inst = insts_to_rename.front();
578
579 insts_to_rename.pop_front();
580
581 if (renameStatus[tid] == Unblocking) {
582 DPRINTF(Rename,"[tid:%u]: Removing [sn:%lli] PC:%s from rename "
583 "skidBuffer\n", tid, inst->seqNum, inst->pcState());
584 }
585
586 if (inst->isSquashed()) {
587 DPRINTF(Rename, "[tid:%u]: instruction %i with PC %s is "
588 "squashed, skipping.\n", tid, inst->seqNum,
589 inst->pcState());
590
591 ++renameSquashedInsts;
592
593 // Decrement how many instructions are available.
594 --insts_available;
595
596 continue;
597 }
598
599 DPRINTF(Rename, "[tid:%u]: Processing instruction [sn:%lli] with "
600 "PC %s.\n", tid, inst->seqNum, inst->pcState());
601
602 // Handle serializeAfter/serializeBefore instructions.
603 // serializeAfter marks the next instruction as serializeBefore.
604 // serializeBefore makes the instruction wait in rename until the ROB
605 // is empty.
606
607 // In this model, IPR accesses are serialize before
608 // instructions, and store conditionals are serialize after
609 // instructions. This is mainly due to lack of support for
610 // out-of-order operations of either of those classes of
611 // instructions.
612 if ((inst->isIprAccess() || inst->isSerializeBefore()) &&
613 !inst->isSerializeHandled()) {
614 DPRINTF(Rename, "Serialize before instruction encountered.\n");
615
616 if (!inst->isTempSerializeBefore()) {
617 renamedSerializing++;
618 inst->setSerializeHandled();
619 } else {
620 renamedTempSerializing++;
621 }
622
623 // Change status over to SerializeStall so that other stages know
624 // what this is blocked on.
625 renameStatus[tid] = SerializeStall;
626
627 serializeInst[tid] = inst;
628
629 blockThisCycle = true;
630
631 break;
632 } else if ((inst->isStoreConditional() || inst->isSerializeAfter()) &&
633 !inst->isSerializeHandled()) {
634 DPRINTF(Rename, "Serialize after instruction encountered.\n");
635
636 renamedSerializing++;
637
638 inst->setSerializeHandled();
639
640 serializeAfter(insts_to_rename, tid);
641 }
642
643 // Check here to make sure there are enough destination registers
644 // to rename to. Otherwise block.
645 if (renameMap[tid]->numFreeEntries() < inst->numDestRegs()) {
646 DPRINTF(Rename, "Blocking due to lack of free "
647 "physical registers to rename to.\n");
648 blockThisCycle = true;
649 insts_to_rename.push_front(inst);
650 ++renameFullRegistersEvents;
651
652 break;
653 }
654
655 renameSrcRegs(inst, inst->threadNumber);
656
657 renameDestRegs(inst, inst->threadNumber);
658
659 ++renamed_insts;
660
53#include "params/DerivO3CPU.hh"
54
55using namespace std;
56
57template <class Impl>
58DefaultRename<Impl>::DefaultRename(O3CPU *_cpu, DerivO3CPUParams *params)
59 : cpu(_cpu),
60 iewToRenameDelay(params->iewToRenameDelay),
61 decodeToRenameDelay(params->decodeToRenameDelay),
62 commitToRenameDelay(params->commitToRenameDelay),
63 renameWidth(params->renameWidth),
64 commitWidth(params->commitWidth),
65 numThreads(params->numThreads),
66 maxPhysicalRegs(params->numPhysIntRegs + params->numPhysFloatRegs)
67{
68 // @todo: Make into a parameter.
69 skidBufferMax = (2 * (decodeToRenameDelay * params->decodeWidth)) + renameWidth;
70}
71
72template <class Impl>
73std::string
74DefaultRename<Impl>::name() const
75{
76 return cpu->name() + ".rename";
77}
78
79template <class Impl>
80void
81DefaultRename<Impl>::regStats()
82{
83 renameSquashCycles
84 .name(name() + ".SquashCycles")
85 .desc("Number of cycles rename is squashing")
86 .prereq(renameSquashCycles);
87 renameIdleCycles
88 .name(name() + ".IdleCycles")
89 .desc("Number of cycles rename is idle")
90 .prereq(renameIdleCycles);
91 renameBlockCycles
92 .name(name() + ".BlockCycles")
93 .desc("Number of cycles rename is blocking")
94 .prereq(renameBlockCycles);
95 renameSerializeStallCycles
96 .name(name() + ".serializeStallCycles")
97 .desc("count of cycles rename stalled for serializing inst")
98 .flags(Stats::total);
99 renameRunCycles
100 .name(name() + ".RunCycles")
101 .desc("Number of cycles rename is running")
102 .prereq(renameIdleCycles);
103 renameUnblockCycles
104 .name(name() + ".UnblockCycles")
105 .desc("Number of cycles rename is unblocking")
106 .prereq(renameUnblockCycles);
107 renameRenamedInsts
108 .name(name() + ".RenamedInsts")
109 .desc("Number of instructions processed by rename")
110 .prereq(renameRenamedInsts);
111 renameSquashedInsts
112 .name(name() + ".SquashedInsts")
113 .desc("Number of squashed instructions processed by rename")
114 .prereq(renameSquashedInsts);
115 renameROBFullEvents
116 .name(name() + ".ROBFullEvents")
117 .desc("Number of times rename has blocked due to ROB full")
118 .prereq(renameROBFullEvents);
119 renameIQFullEvents
120 .name(name() + ".IQFullEvents")
121 .desc("Number of times rename has blocked due to IQ full")
122 .prereq(renameIQFullEvents);
123 renameLSQFullEvents
124 .name(name() + ".LSQFullEvents")
125 .desc("Number of times rename has blocked due to LSQ full")
126 .prereq(renameLSQFullEvents);
127 renameFullRegistersEvents
128 .name(name() + ".FullRegisterEvents")
129 .desc("Number of times there has been no free registers")
130 .prereq(renameFullRegistersEvents);
131 renameRenamedOperands
132 .name(name() + ".RenamedOperands")
133 .desc("Number of destination operands rename has renamed")
134 .prereq(renameRenamedOperands);
135 renameRenameLookups
136 .name(name() + ".RenameLookups")
137 .desc("Number of register rename lookups that rename has made")
138 .prereq(renameRenameLookups);
139 renameCommittedMaps
140 .name(name() + ".CommittedMaps")
141 .desc("Number of HB maps that are committed")
142 .prereq(renameCommittedMaps);
143 renameUndoneMaps
144 .name(name() + ".UndoneMaps")
145 .desc("Number of HB maps that are undone due to squashing")
146 .prereq(renameUndoneMaps);
147 renamedSerializing
148 .name(name() + ".serializingInsts")
149 .desc("count of serializing insts renamed")
150 .flags(Stats::total)
151 ;
152 renamedTempSerializing
153 .name(name() + ".tempSerializingInsts")
154 .desc("count of temporary serializing insts renamed")
155 .flags(Stats::total)
156 ;
157 renameSkidInsts
158 .name(name() + ".skidInsts")
159 .desc("count of insts added to the skid buffer")
160 .flags(Stats::total)
161 ;
162 intRenameLookups
163 .name(name() + ".int_rename_lookups")
164 .desc("Number of integer rename lookups")
165 .prereq(intRenameLookups);
166 fpRenameLookups
167 .name(name() + ".fp_rename_lookups")
168 .desc("Number of floating rename lookups")
169 .prereq(fpRenameLookups);
170}
171
172template <class Impl>
173void
174DefaultRename<Impl>::setTimeBuffer(TimeBuffer<TimeStruct> *tb_ptr)
175{
176 timeBuffer = tb_ptr;
177
178 // Setup wire to read information from time buffer, from IEW stage.
179 fromIEW = timeBuffer->getWire(-iewToRenameDelay);
180
181 // Setup wire to read infromation from time buffer, from commit stage.
182 fromCommit = timeBuffer->getWire(-commitToRenameDelay);
183
184 // Setup wire to write information to previous stages.
185 toDecode = timeBuffer->getWire(0);
186}
187
188template <class Impl>
189void
190DefaultRename<Impl>::setRenameQueue(TimeBuffer<RenameStruct> *rq_ptr)
191{
192 renameQueue = rq_ptr;
193
194 // Setup wire to write information to future stages.
195 toIEW = renameQueue->getWire(0);
196}
197
198template <class Impl>
199void
200DefaultRename<Impl>::setDecodeQueue(TimeBuffer<DecodeStruct> *dq_ptr)
201{
202 decodeQueue = dq_ptr;
203
204 // Setup wire to get information from decode.
205 fromDecode = decodeQueue->getWire(-decodeToRenameDelay);
206}
207
208template <class Impl>
209void
210DefaultRename<Impl>::startupStage()
211{
212 resetStage();
213}
214
215template <class Impl>
216void
217DefaultRename<Impl>::resetStage()
218{
219 _status = Inactive;
220
221 resumeSerialize = false;
222 resumeUnblocking = false;
223
224 // Grab the number of free entries directly from the stages.
225 for (ThreadID tid = 0; tid < numThreads; tid++) {
226 renameStatus[tid] = Idle;
227
228 freeEntries[tid].iqEntries = iew_ptr->instQueue.numFreeEntries(tid);
229 freeEntries[tid].lsqEntries = iew_ptr->ldstQueue.numFreeEntries(tid);
230 freeEntries[tid].robEntries = commit_ptr->numROBFreeEntries(tid);
231 emptyROB[tid] = true;
232
233 stalls[tid].iew = false;
234 stalls[tid].commit = false;
235 serializeInst[tid] = NULL;
236
237 instsInProgress[tid] = 0;
238
239 serializeOnNextInst[tid] = false;
240 }
241}
242
243template<class Impl>
244void
245DefaultRename<Impl>::setActiveThreads(list<ThreadID> *at_ptr)
246{
247 activeThreads = at_ptr;
248}
249
250
251template <class Impl>
252void
253DefaultRename<Impl>::setRenameMap(RenameMap rm_ptr[])
254{
255 for (ThreadID tid = 0; tid < numThreads; tid++)
256 renameMap[tid] = &rm_ptr[tid];
257}
258
259template <class Impl>
260void
261DefaultRename<Impl>::setFreeList(FreeList *fl_ptr)
262{
263 freeList = fl_ptr;
264}
265
266template<class Impl>
267void
268DefaultRename<Impl>::setScoreboard(Scoreboard *_scoreboard)
269{
270 scoreboard = _scoreboard;
271}
272
273template <class Impl>
274bool
275DefaultRename<Impl>::isDrained() const
276{
277 for (ThreadID tid = 0; tid < numThreads; tid++) {
278 if (instsInProgress[tid] != 0 ||
279 !historyBuffer[tid].empty() ||
280 !skidBuffer[tid].empty() ||
281 !insts[tid].empty())
282 return false;
283 }
284 return true;
285}
286
287template <class Impl>
288void
289DefaultRename<Impl>::takeOverFrom()
290{
291 resetStage();
292}
293
294template <class Impl>
295void
296DefaultRename<Impl>::drainSanityCheck() const
297{
298 for (ThreadID tid = 0; tid < numThreads; tid++) {
299 assert(historyBuffer[tid].empty());
300 assert(insts[tid].empty());
301 assert(skidBuffer[tid].empty());
302 assert(instsInProgress[tid] == 0);
303 }
304}
305
306template <class Impl>
307void
308DefaultRename<Impl>::squash(const InstSeqNum &squash_seq_num, ThreadID tid)
309{
310 DPRINTF(Rename, "[tid:%u]: Squashing instructions.\n",tid);
311
312 // Clear the stall signal if rename was blocked or unblocking before.
313 // If it still needs to block, the blocking should happen the next
314 // cycle and there should be space to hold everything due to the squash.
315 if (renameStatus[tid] == Blocked ||
316 renameStatus[tid] == Unblocking) {
317 toDecode->renameUnblock[tid] = 1;
318
319 resumeSerialize = false;
320 serializeInst[tid] = NULL;
321 } else if (renameStatus[tid] == SerializeStall) {
322 if (serializeInst[tid]->seqNum <= squash_seq_num) {
323 DPRINTF(Rename, "Rename will resume serializing after squash\n");
324 resumeSerialize = true;
325 assert(serializeInst[tid]);
326 } else {
327 resumeSerialize = false;
328 toDecode->renameUnblock[tid] = 1;
329
330 serializeInst[tid] = NULL;
331 }
332 }
333
334 // Set the status to Squashing.
335 renameStatus[tid] = Squashing;
336
337 // Squash any instructions from decode.
338 unsigned squashCount = 0;
339
340 for (int i=0; i<fromDecode->size; i++) {
341 if (fromDecode->insts[i]->threadNumber == tid &&
342 fromDecode->insts[i]->seqNum > squash_seq_num) {
343 fromDecode->insts[i]->setSquashed();
344 wroteToTimeBuffer = true;
345 squashCount++;
346 }
347
348 }
349
350 // Clear the instruction list and skid buffer in case they have any
351 // insts in them.
352 insts[tid].clear();
353
354 // Clear the skid buffer in case it has any data in it.
355 skidBuffer[tid].clear();
356
357 doSquash(squash_seq_num, tid);
358}
359
360template <class Impl>
361void
362DefaultRename<Impl>::tick()
363{
364 wroteToTimeBuffer = false;
365
366 blockThisCycle = false;
367
368 bool status_change = false;
369
370 toIEWIndex = 0;
371
372 sortInsts();
373
374 list<ThreadID>::iterator threads = activeThreads->begin();
375 list<ThreadID>::iterator end = activeThreads->end();
376
377 // Check stall and squash signals.
378 while (threads != end) {
379 ThreadID tid = *threads++;
380
381 DPRINTF(Rename, "Processing [tid:%i]\n", tid);
382
383 status_change = checkSignalsAndUpdate(tid) || status_change;
384
385 rename(status_change, tid);
386 }
387
388 if (status_change) {
389 updateStatus();
390 }
391
392 if (wroteToTimeBuffer) {
393 DPRINTF(Activity, "Activity this cycle.\n");
394 cpu->activityThisCycle();
395 }
396
397 threads = activeThreads->begin();
398
399 while (threads != end) {
400 ThreadID tid = *threads++;
401
402 // If we committed this cycle then doneSeqNum will be > 0
403 if (fromCommit->commitInfo[tid].doneSeqNum != 0 &&
404 !fromCommit->commitInfo[tid].squash &&
405 renameStatus[tid] != Squashing) {
406
407 removeFromHistory(fromCommit->commitInfo[tid].doneSeqNum,
408 tid);
409 }
410 }
411
412 // @todo: make into updateProgress function
413 for (ThreadID tid = 0; tid < numThreads; tid++) {
414 instsInProgress[tid] -= fromIEW->iewInfo[tid].dispatched;
415
416 assert(instsInProgress[tid] >=0);
417 }
418
419}
420
421template<class Impl>
422void
423DefaultRename<Impl>::rename(bool &status_change, ThreadID tid)
424{
425 // If status is Running or idle,
426 // call renameInsts()
427 // If status is Unblocking,
428 // buffer any instructions coming from decode
429 // continue trying to empty skid buffer
430 // check if stall conditions have passed
431
432 if (renameStatus[tid] == Blocked) {
433 ++renameBlockCycles;
434 } else if (renameStatus[tid] == Squashing) {
435 ++renameSquashCycles;
436 } else if (renameStatus[tid] == SerializeStall) {
437 ++renameSerializeStallCycles;
438 // If we are currently in SerializeStall and resumeSerialize
439 // was set, then that means that we are resuming serializing
440 // this cycle. Tell the previous stages to block.
441 if (resumeSerialize) {
442 resumeSerialize = false;
443 block(tid);
444 toDecode->renameUnblock[tid] = false;
445 }
446 } else if (renameStatus[tid] == Unblocking) {
447 if (resumeUnblocking) {
448 block(tid);
449 resumeUnblocking = false;
450 toDecode->renameUnblock[tid] = false;
451 }
452 }
453
454 if (renameStatus[tid] == Running ||
455 renameStatus[tid] == Idle) {
456 DPRINTF(Rename, "[tid:%u]: Not blocked, so attempting to run "
457 "stage.\n", tid);
458
459 renameInsts(tid);
460 } else if (renameStatus[tid] == Unblocking) {
461 renameInsts(tid);
462
463 if (validInsts()) {
464 // Add the current inputs to the skid buffer so they can be
465 // reprocessed when this stage unblocks.
466 skidInsert(tid);
467 }
468
469 // If we switched over to blocking, then there's a potential for
470 // an overall status change.
471 status_change = unblock(tid) || status_change || blockThisCycle;
472 }
473}
474
475template <class Impl>
476void
477DefaultRename<Impl>::renameInsts(ThreadID tid)
478{
479 // Instructions can be either in the skid buffer or the queue of
480 // instructions coming from decode, depending on the status.
481 int insts_available = renameStatus[tid] == Unblocking ?
482 skidBuffer[tid].size() : insts[tid].size();
483
484 // Check the decode queue to see if instructions are available.
485 // If there are no available instructions to rename, then do nothing.
486 if (insts_available == 0) {
487 DPRINTF(Rename, "[tid:%u]: Nothing to do, breaking out early.\n",
488 tid);
489 // Should I change status to idle?
490 ++renameIdleCycles;
491 return;
492 } else if (renameStatus[tid] == Unblocking) {
493 ++renameUnblockCycles;
494 } else if (renameStatus[tid] == Running) {
495 ++renameRunCycles;
496 }
497
498 DynInstPtr inst;
499
500 // Will have to do a different calculation for the number of free
501 // entries.
502 int free_rob_entries = calcFreeROBEntries(tid);
503 int free_iq_entries = calcFreeIQEntries(tid);
504 int free_lsq_entries = calcFreeLSQEntries(tid);
505 int min_free_entries = free_rob_entries;
506
507 FullSource source = ROB;
508
509 if (free_iq_entries < min_free_entries) {
510 min_free_entries = free_iq_entries;
511 source = IQ;
512 }
513
514 if (free_lsq_entries < min_free_entries) {
515 min_free_entries = free_lsq_entries;
516 source = LSQ;
517 }
518
519 // Check if there's any space left.
520 if (min_free_entries <= 0) {
521 DPRINTF(Rename, "[tid:%u]: Blocking due to no free ROB/IQ/LSQ "
522 "entries.\n"
523 "ROB has %i free entries.\n"
524 "IQ has %i free entries.\n"
525 "LSQ has %i free entries.\n",
526 tid,
527 free_rob_entries,
528 free_iq_entries,
529 free_lsq_entries);
530
531 blockThisCycle = true;
532
533 block(tid);
534
535 incrFullStat(source);
536
537 return;
538 } else if (min_free_entries < insts_available) {
539 DPRINTF(Rename, "[tid:%u]: Will have to block this cycle."
540 "%i insts available, but only %i insts can be "
541 "renamed due to ROB/IQ/LSQ limits.\n",
542 tid, insts_available, min_free_entries);
543
544 insts_available = min_free_entries;
545
546 blockThisCycle = true;
547
548 incrFullStat(source);
549 }
550
551 InstQueue &insts_to_rename = renameStatus[tid] == Unblocking ?
552 skidBuffer[tid] : insts[tid];
553
554 DPRINTF(Rename, "[tid:%u]: %i available instructions to "
555 "send iew.\n", tid, insts_available);
556
557 DPRINTF(Rename, "[tid:%u]: %i insts pipelining from Rename | %i insts "
558 "dispatched to IQ last cycle.\n",
559 tid, instsInProgress[tid], fromIEW->iewInfo[tid].dispatched);
560
561 // Handle serializing the next instruction if necessary.
562 if (serializeOnNextInst[tid]) {
563 if (emptyROB[tid] && instsInProgress[tid] == 0) {
564 // ROB already empty; no need to serialize.
565 serializeOnNextInst[tid] = false;
566 } else if (!insts_to_rename.empty()) {
567 insts_to_rename.front()->setSerializeBefore();
568 }
569 }
570
571 int renamed_insts = 0;
572
573 while (insts_available > 0 && toIEWIndex < renameWidth) {
574 DPRINTF(Rename, "[tid:%u]: Sending instructions to IEW.\n", tid);
575
576 assert(!insts_to_rename.empty());
577
578 inst = insts_to_rename.front();
579
580 insts_to_rename.pop_front();
581
582 if (renameStatus[tid] == Unblocking) {
583 DPRINTF(Rename,"[tid:%u]: Removing [sn:%lli] PC:%s from rename "
584 "skidBuffer\n", tid, inst->seqNum, inst->pcState());
585 }
586
587 if (inst->isSquashed()) {
588 DPRINTF(Rename, "[tid:%u]: instruction %i with PC %s is "
589 "squashed, skipping.\n", tid, inst->seqNum,
590 inst->pcState());
591
592 ++renameSquashedInsts;
593
594 // Decrement how many instructions are available.
595 --insts_available;
596
597 continue;
598 }
599
600 DPRINTF(Rename, "[tid:%u]: Processing instruction [sn:%lli] with "
601 "PC %s.\n", tid, inst->seqNum, inst->pcState());
602
603 // Handle serializeAfter/serializeBefore instructions.
604 // serializeAfter marks the next instruction as serializeBefore.
605 // serializeBefore makes the instruction wait in rename until the ROB
606 // is empty.
607
608 // In this model, IPR accesses are serialize before
609 // instructions, and store conditionals are serialize after
610 // instructions. This is mainly due to lack of support for
611 // out-of-order operations of either of those classes of
612 // instructions.
613 if ((inst->isIprAccess() || inst->isSerializeBefore()) &&
614 !inst->isSerializeHandled()) {
615 DPRINTF(Rename, "Serialize before instruction encountered.\n");
616
617 if (!inst->isTempSerializeBefore()) {
618 renamedSerializing++;
619 inst->setSerializeHandled();
620 } else {
621 renamedTempSerializing++;
622 }
623
624 // Change status over to SerializeStall so that other stages know
625 // what this is blocked on.
626 renameStatus[tid] = SerializeStall;
627
628 serializeInst[tid] = inst;
629
630 blockThisCycle = true;
631
632 break;
633 } else if ((inst->isStoreConditional() || inst->isSerializeAfter()) &&
634 !inst->isSerializeHandled()) {
635 DPRINTF(Rename, "Serialize after instruction encountered.\n");
636
637 renamedSerializing++;
638
639 inst->setSerializeHandled();
640
641 serializeAfter(insts_to_rename, tid);
642 }
643
644 // Check here to make sure there are enough destination registers
645 // to rename to. Otherwise block.
646 if (renameMap[tid]->numFreeEntries() < inst->numDestRegs()) {
647 DPRINTF(Rename, "Blocking due to lack of free "
648 "physical registers to rename to.\n");
649 blockThisCycle = true;
650 insts_to_rename.push_front(inst);
651 ++renameFullRegistersEvents;
652
653 break;
654 }
655
656 renameSrcRegs(inst, inst->threadNumber);
657
658 renameDestRegs(inst, inst->threadNumber);
659
660 ++renamed_insts;
661
661#if TRACING_ON
662 inst->renameTick = curTick() - inst->fetchTick;
663#endif
664
665 // Put instruction in rename queue.
666 toIEW->insts[toIEWIndex] = inst;
667 ++(toIEW->size);
668
669 // Increment which instruction we're on.
670 ++toIEWIndex;
671
672 // Decrement how many instructions are available.
673 --insts_available;
674 }
675
676 instsInProgress[tid] += renamed_insts;
677 renameRenamedInsts += renamed_insts;
678
679 // If we wrote to the time buffer, record this.
680 if (toIEWIndex) {
681 wroteToTimeBuffer = true;
682 }
683
684 // Check if there's any instructions left that haven't yet been renamed.
685 // If so then block.
686 if (insts_available) {
687 blockThisCycle = true;
688 }
689
690 if (blockThisCycle) {
691 block(tid);
692 toDecode->renameUnblock[tid] = false;
693 }
694}
695
696template<class Impl>
697void
698DefaultRename<Impl>::skidInsert(ThreadID tid)
699{
700 DynInstPtr inst = NULL;
701
702 while (!insts[tid].empty()) {
703 inst = insts[tid].front();
704
705 insts[tid].pop_front();
706
707 assert(tid == inst->threadNumber);
708
709 DPRINTF(Rename, "[tid:%u]: Inserting [sn:%lli] PC: %s into Rename "
710 "skidBuffer\n", tid, inst->seqNum, inst->pcState());
711
712 ++renameSkidInsts;
713
714 skidBuffer[tid].push_back(inst);
715 }
716
717 if (skidBuffer[tid].size() > skidBufferMax)
718 {
719 typename InstQueue::iterator it;
720 warn("Skidbuffer contents:\n");
721 for(it = skidBuffer[tid].begin(); it != skidBuffer[tid].end(); it++)
722 {
723 warn("[tid:%u]: %s [sn:%i].\n", tid,
724 (*it)->staticInst->disassemble(inst->instAddr()),
725 (*it)->seqNum);
726 }
727 panic("Skidbuffer Exceeded Max Size");
728 }
729}
730
731template <class Impl>
732void
733DefaultRename<Impl>::sortInsts()
734{
735 int insts_from_decode = fromDecode->size;
736 for (int i = 0; i < insts_from_decode; ++i) {
737 DynInstPtr inst = fromDecode->insts[i];
738 insts[inst->threadNumber].push_back(inst);
662
663 // Put instruction in rename queue.
664 toIEW->insts[toIEWIndex] = inst;
665 ++(toIEW->size);
666
667 // Increment which instruction we're on.
668 ++toIEWIndex;
669
670 // Decrement how many instructions are available.
671 --insts_available;
672 }
673
674 instsInProgress[tid] += renamed_insts;
675 renameRenamedInsts += renamed_insts;
676
677 // If we wrote to the time buffer, record this.
678 if (toIEWIndex) {
679 wroteToTimeBuffer = true;
680 }
681
682 // Check if there's any instructions left that haven't yet been renamed.
683 // If so then block.
684 if (insts_available) {
685 blockThisCycle = true;
686 }
687
688 if (blockThisCycle) {
689 block(tid);
690 toDecode->renameUnblock[tid] = false;
691 }
692}
693
694template<class Impl>
695void
696DefaultRename<Impl>::skidInsert(ThreadID tid)
697{
698 DynInstPtr inst = NULL;
699
700 while (!insts[tid].empty()) {
701 inst = insts[tid].front();
702
703 insts[tid].pop_front();
704
705 assert(tid == inst->threadNumber);
706
707 DPRINTF(Rename, "[tid:%u]: Inserting [sn:%lli] PC: %s into Rename "
708 "skidBuffer\n", tid, inst->seqNum, inst->pcState());
709
710 ++renameSkidInsts;
711
712 skidBuffer[tid].push_back(inst);
713 }
714
715 if (skidBuffer[tid].size() > skidBufferMax)
716 {
717 typename InstQueue::iterator it;
718 warn("Skidbuffer contents:\n");
719 for(it = skidBuffer[tid].begin(); it != skidBuffer[tid].end(); it++)
720 {
721 warn("[tid:%u]: %s [sn:%i].\n", tid,
722 (*it)->staticInst->disassemble(inst->instAddr()),
723 (*it)->seqNum);
724 }
725 panic("Skidbuffer Exceeded Max Size");
726 }
727}
728
729template <class Impl>
730void
731DefaultRename<Impl>::sortInsts()
732{
733 int insts_from_decode = fromDecode->size;
734 for (int i = 0; i < insts_from_decode; ++i) {
735 DynInstPtr inst = fromDecode->insts[i];
736 insts[inst->threadNumber].push_back(inst);
737#if TRACING_ON
738 if (DTRACE(O3PipeView)) {
739 inst->renameTick = curTick() - inst->fetchTick;
740 }
741#endif
739 }
740}
741
742template<class Impl>
743bool
744DefaultRename<Impl>::skidsEmpty()
745{
746 list<ThreadID>::iterator threads = activeThreads->begin();
747 list<ThreadID>::iterator end = activeThreads->end();
748
749 while (threads != end) {
750 ThreadID tid = *threads++;
751
752 if (!skidBuffer[tid].empty())
753 return false;
754 }
755
756 return true;
757}
758
759template<class Impl>
760void
761DefaultRename<Impl>::updateStatus()
762{
763 bool any_unblocking = false;
764
765 list<ThreadID>::iterator threads = activeThreads->begin();
766 list<ThreadID>::iterator end = activeThreads->end();
767
768 while (threads != end) {
769 ThreadID tid = *threads++;
770
771 if (renameStatus[tid] == Unblocking) {
772 any_unblocking = true;
773 break;
774 }
775 }
776
777 // Rename will have activity if it's unblocking.
778 if (any_unblocking) {
779 if (_status == Inactive) {
780 _status = Active;
781
782 DPRINTF(Activity, "Activating stage.\n");
783
784 cpu->activateStage(O3CPU::RenameIdx);
785 }
786 } else {
787 // If it's not unblocking, then rename will not have any internal
788 // activity. Switch it to inactive.
789 if (_status == Active) {
790 _status = Inactive;
791 DPRINTF(Activity, "Deactivating stage.\n");
792
793 cpu->deactivateStage(O3CPU::RenameIdx);
794 }
795 }
796}
797
798template <class Impl>
799bool
800DefaultRename<Impl>::block(ThreadID tid)
801{
802 DPRINTF(Rename, "[tid:%u]: Blocking.\n", tid);
803
804 // Add the current inputs onto the skid buffer, so they can be
805 // reprocessed when this stage unblocks.
806 skidInsert(tid);
807
808 // Only signal backwards to block if the previous stages do not think
809 // rename is already blocked.
810 if (renameStatus[tid] != Blocked) {
811 // If resumeUnblocking is set, we unblocked during the squash,
812 // but now we're have unblocking status. We need to tell earlier
813 // stages to block.
814 if (resumeUnblocking || renameStatus[tid] != Unblocking) {
815 toDecode->renameBlock[tid] = true;
816 toDecode->renameUnblock[tid] = false;
817 wroteToTimeBuffer = true;
818 }
819
820 // Rename can not go from SerializeStall to Blocked, otherwise
821 // it would not know to complete the serialize stall.
822 if (renameStatus[tid] != SerializeStall) {
823 // Set status to Blocked.
824 renameStatus[tid] = Blocked;
825 return true;
826 }
827 }
828
829 return false;
830}
831
832template <class Impl>
833bool
834DefaultRename<Impl>::unblock(ThreadID tid)
835{
836 DPRINTF(Rename, "[tid:%u]: Trying to unblock.\n", tid);
837
838 // Rename is done unblocking if the skid buffer is empty.
839 if (skidBuffer[tid].empty() && renameStatus[tid] != SerializeStall) {
840
841 DPRINTF(Rename, "[tid:%u]: Done unblocking.\n", tid);
842
843 toDecode->renameUnblock[tid] = true;
844 wroteToTimeBuffer = true;
845
846 renameStatus[tid] = Running;
847 return true;
848 }
849
850 return false;
851}
852
853template <class Impl>
854void
855DefaultRename<Impl>::doSquash(const InstSeqNum &squashed_seq_num, ThreadID tid)
856{
857 typename std::list<RenameHistory>::iterator hb_it =
858 historyBuffer[tid].begin();
859
860 // After a syscall squashes everything, the history buffer may be empty
861 // but the ROB may still be squashing instructions.
862 if (historyBuffer[tid].empty()) {
863 return;
864 }
865
866 // Go through the most recent instructions, undoing the mappings
867 // they did and freeing up the registers.
868 while (!historyBuffer[tid].empty() &&
869 (*hb_it).instSeqNum > squashed_seq_num) {
870 assert(hb_it != historyBuffer[tid].end());
871
872 DPRINTF(Rename, "[tid:%u]: Removing history entry with sequence "
873 "number %i.\n", tid, (*hb_it).instSeqNum);
874
875 // Tell the rename map to set the architected register to the
876 // previous physical register that it was renamed to.
877 renameMap[tid]->setEntry(hb_it->archReg, hb_it->prevPhysReg);
878
879 // Put the renamed physical register back on the free list.
880 freeList->addReg(hb_it->newPhysReg);
881
882 // Be sure to mark its register as ready if it's a misc register.
883 if (hb_it->newPhysReg >= maxPhysicalRegs) {
884 scoreboard->setReg(hb_it->newPhysReg);
885 }
886
887 historyBuffer[tid].erase(hb_it++);
888
889 ++renameUndoneMaps;
890 }
891}
892
893template<class Impl>
894void
895DefaultRename<Impl>::removeFromHistory(InstSeqNum inst_seq_num, ThreadID tid)
896{
897 DPRINTF(Rename, "[tid:%u]: Removing a committed instruction from the "
898 "history buffer %u (size=%i), until [sn:%lli].\n",
899 tid, tid, historyBuffer[tid].size(), inst_seq_num);
900
901 typename std::list<RenameHistory>::iterator hb_it =
902 historyBuffer[tid].end();
903
904 --hb_it;
905
906 if (historyBuffer[tid].empty()) {
907 DPRINTF(Rename, "[tid:%u]: History buffer is empty.\n", tid);
908 return;
909 } else if (hb_it->instSeqNum > inst_seq_num) {
910 DPRINTF(Rename, "[tid:%u]: Old sequence number encountered. Ensure "
911 "that a syscall happened recently.\n", tid);
912 return;
913 }
914
915 // Commit all the renames up until (and including) the committed sequence
916 // number. Some or even all of the committed instructions may not have
917 // rename histories if they did not have destination registers that were
918 // renamed.
919 while (!historyBuffer[tid].empty() &&
920 hb_it != historyBuffer[tid].end() &&
921 (*hb_it).instSeqNum <= inst_seq_num) {
922
923 DPRINTF(Rename, "[tid:%u]: Freeing up older rename of reg %i, "
924 "[sn:%lli].\n",
925 tid, (*hb_it).prevPhysReg, (*hb_it).instSeqNum);
926
927 freeList->addReg((*hb_it).prevPhysReg);
928 ++renameCommittedMaps;
929
930 historyBuffer[tid].erase(hb_it--);
931 }
932}
933
934template <class Impl>
935inline void
936DefaultRename<Impl>::renameSrcRegs(DynInstPtr &inst, ThreadID tid)
937{
938 assert(renameMap[tid] != 0);
939
940 unsigned num_src_regs = inst->numSrcRegs();
941
942 // Get the architectual register numbers from the source and
943 // destination operands, and redirect them to the right register.
944 // Will need to mark dependencies though.
945 for (int src_idx = 0; src_idx < num_src_regs; src_idx++) {
946 RegIndex src_reg = inst->srcRegIdx(src_idx);
947 RegIndex flat_src_reg = src_reg;
948 if (src_reg < TheISA::FP_Base_DepTag) {
949 flat_src_reg = inst->tcBase()->flattenIntIndex(src_reg);
950 DPRINTF(Rename, "Flattening index %d to %d.\n",
951 (int)src_reg, (int)flat_src_reg);
952 } else if (src_reg < TheISA::Ctrl_Base_DepTag) {
953 src_reg = src_reg - TheISA::FP_Base_DepTag;
954 flat_src_reg = inst->tcBase()->flattenFloatIndex(src_reg);
955 DPRINTF(Rename, "Flattening index %d to %d.\n",
956 (int)src_reg, (int)flat_src_reg);
957 flat_src_reg += TheISA::NumIntRegs;
958 } else if (src_reg < TheISA::Max_DepTag) {
959 flat_src_reg = src_reg - TheISA::Ctrl_Base_DepTag +
960 TheISA::NumFloatRegs + TheISA::NumIntRegs;
961 DPRINTF(Rename, "Adjusting reg index from %d to %d.\n",
962 src_reg, flat_src_reg);
963 } else {
964 panic("Reg index is out of bound: %d.", src_reg);
965 }
966
967 // Look up the source registers to get the phys. register they've
968 // been renamed to, and set the sources to those registers.
969 PhysRegIndex renamed_reg = renameMap[tid]->lookup(flat_src_reg);
970
971 DPRINTF(Rename, "[tid:%u]: Looking up arch reg %i, got "
972 "physical reg %i.\n", tid, (int)flat_src_reg,
973 (int)renamed_reg);
974
975 inst->renameSrcReg(src_idx, renamed_reg);
976
977 // See if the register is ready or not.
978 if (scoreboard->getReg(renamed_reg) == true) {
979 DPRINTF(Rename, "[tid:%u]: Register %d is ready.\n",
980 tid, renamed_reg);
981
982 inst->markSrcRegReady(src_idx);
983 } else {
984 DPRINTF(Rename, "[tid:%u]: Register %d is not ready.\n",
985 tid, renamed_reg);
986 }
987
988 ++renameRenameLookups;
989 inst->isFloating() ? fpRenameLookups++ : intRenameLookups++;
990 }
991}
992
993template <class Impl>
994inline void
995DefaultRename<Impl>::renameDestRegs(DynInstPtr &inst, ThreadID tid)
996{
997 typename RenameMap::RenameInfo rename_result;
998
999 unsigned num_dest_regs = inst->numDestRegs();
1000
1001 // Rename the destination registers.
1002 for (int dest_idx = 0; dest_idx < num_dest_regs; dest_idx++) {
1003 RegIndex dest_reg = inst->destRegIdx(dest_idx);
1004 RegIndex flat_dest_reg = dest_reg;
1005 if (dest_reg < TheISA::FP_Base_DepTag) {
1006 // Integer registers are flattened.
1007 flat_dest_reg = inst->tcBase()->flattenIntIndex(dest_reg);
1008 DPRINTF(Rename, "Flattening index %d to %d.\n",
1009 (int)dest_reg, (int)flat_dest_reg);
1010 } else if (dest_reg < TheISA::Ctrl_Base_DepTag) {
1011 dest_reg = dest_reg - TheISA::FP_Base_DepTag;
1012 flat_dest_reg = inst->tcBase()->flattenFloatIndex(dest_reg);
1013 DPRINTF(Rename, "Flattening index %d to %d.\n",
1014 (int)dest_reg, (int)flat_dest_reg);
1015 flat_dest_reg += TheISA::NumIntRegs;
1016 } else if (dest_reg < TheISA::Max_DepTag) {
1017 // Floating point and Miscellaneous registers need their indexes
1018 // adjusted to account for the expanded number of flattened int regs.
1019 flat_dest_reg = dest_reg - TheISA::Ctrl_Base_DepTag +
1020 TheISA::NumIntRegs + TheISA::NumFloatRegs;
1021 DPRINTF(Rename, "Adjusting reg index from %d to %d.\n",
1022 dest_reg, flat_dest_reg);
1023 } else {
1024 panic("Reg index is out of bound: %d.", dest_reg);
1025 }
1026
1027 inst->flattenDestReg(dest_idx, flat_dest_reg);
1028
1029 // Get the physical register that the destination will be
1030 // renamed to.
1031 rename_result = renameMap[tid]->rename(flat_dest_reg);
1032
1033 //Mark Scoreboard entry as not ready
1034 if (dest_reg < TheISA::Ctrl_Base_DepTag)
1035 scoreboard->unsetReg(rename_result.first);
1036
1037 DPRINTF(Rename, "[tid:%u]: Renaming arch reg %i to physical "
1038 "reg %i.\n", tid, (int)flat_dest_reg,
1039 (int)rename_result.first);
1040
1041 // Record the rename information so that a history can be kept.
1042 RenameHistory hb_entry(inst->seqNum, flat_dest_reg,
1043 rename_result.first,
1044 rename_result.second);
1045
1046 historyBuffer[tid].push_front(hb_entry);
1047
1048 DPRINTF(Rename, "[tid:%u]: Adding instruction to history buffer "
1049 "(size=%i), [sn:%lli].\n",tid,
1050 historyBuffer[tid].size(),
1051 (*historyBuffer[tid].begin()).instSeqNum);
1052
1053 // Tell the instruction to rename the appropriate destination
1054 // register (dest_idx) to the new physical register
1055 // (rename_result.first), and record the previous physical
1056 // register that the same logical register was renamed to
1057 // (rename_result.second).
1058 inst->renameDestReg(dest_idx,
1059 rename_result.first,
1060 rename_result.second);
1061
1062 ++renameRenamedOperands;
1063 }
1064}
1065
1066template <class Impl>
1067inline int
1068DefaultRename<Impl>::calcFreeROBEntries(ThreadID tid)
1069{
1070 int num_free = freeEntries[tid].robEntries -
1071 (instsInProgress[tid] - fromIEW->iewInfo[tid].dispatched);
1072
1073 //DPRINTF(Rename,"[tid:%i]: %i rob free\n",tid,num_free);
1074
1075 return num_free;
1076}
1077
1078template <class Impl>
1079inline int
1080DefaultRename<Impl>::calcFreeIQEntries(ThreadID tid)
1081{
1082 int num_free = freeEntries[tid].iqEntries -
1083 (instsInProgress[tid] - fromIEW->iewInfo[tid].dispatched);
1084
1085 //DPRINTF(Rename,"[tid:%i]: %i iq free\n",tid,num_free);
1086
1087 return num_free;
1088}
1089
1090template <class Impl>
1091inline int
1092DefaultRename<Impl>::calcFreeLSQEntries(ThreadID tid)
1093{
1094 int num_free = freeEntries[tid].lsqEntries -
1095 (instsInProgress[tid] - fromIEW->iewInfo[tid].dispatchedToLSQ);
1096
1097 //DPRINTF(Rename,"[tid:%i]: %i lsq free\n",tid,num_free);
1098
1099 return num_free;
1100}
1101
1102template <class Impl>
1103unsigned
1104DefaultRename<Impl>::validInsts()
1105{
1106 unsigned inst_count = 0;
1107
1108 for (int i=0; i<fromDecode->size; i++) {
1109 if (!fromDecode->insts[i]->isSquashed())
1110 inst_count++;
1111 }
1112
1113 return inst_count;
1114}
1115
1116template <class Impl>
1117void
1118DefaultRename<Impl>::readStallSignals(ThreadID tid)
1119{
1120 if (fromIEW->iewBlock[tid]) {
1121 stalls[tid].iew = true;
1122 }
1123
1124 if (fromIEW->iewUnblock[tid]) {
1125 assert(stalls[tid].iew);
1126 stalls[tid].iew = false;
1127 }
1128
1129 if (fromCommit->commitBlock[tid]) {
1130 stalls[tid].commit = true;
1131 }
1132
1133 if (fromCommit->commitUnblock[tid]) {
1134 assert(stalls[tid].commit);
1135 stalls[tid].commit = false;
1136 }
1137}
1138
1139template <class Impl>
1140bool
1141DefaultRename<Impl>::checkStall(ThreadID tid)
1142{
1143 bool ret_val = false;
1144
1145 if (stalls[tid].iew) {
1146 DPRINTF(Rename,"[tid:%i]: Stall from IEW stage detected.\n", tid);
1147 ret_val = true;
1148 } else if (stalls[tid].commit) {
1149 DPRINTF(Rename,"[tid:%i]: Stall from Commit stage detected.\n", tid);
1150 ret_val = true;
1151 } else if (calcFreeROBEntries(tid) <= 0) {
1152 DPRINTF(Rename,"[tid:%i]: Stall: ROB has 0 free entries.\n", tid);
1153 ret_val = true;
1154 } else if (calcFreeIQEntries(tid) <= 0) {
1155 DPRINTF(Rename,"[tid:%i]: Stall: IQ has 0 free entries.\n", tid);
1156 ret_val = true;
1157 } else if (calcFreeLSQEntries(tid) <= 0) {
1158 DPRINTF(Rename,"[tid:%i]: Stall: LSQ has 0 free entries.\n", tid);
1159 ret_val = true;
1160 } else if (renameMap[tid]->numFreeEntries() <= 0) {
1161 DPRINTF(Rename,"[tid:%i]: Stall: RenameMap has 0 free entries.\n", tid);
1162 ret_val = true;
1163 } else if (renameStatus[tid] == SerializeStall &&
1164 (!emptyROB[tid] || instsInProgress[tid])) {
1165 DPRINTF(Rename,"[tid:%i]: Stall: Serialize stall and ROB is not "
1166 "empty.\n",
1167 tid);
1168 ret_val = true;
1169 }
1170
1171 return ret_val;
1172}
1173
1174template <class Impl>
1175void
1176DefaultRename<Impl>::readFreeEntries(ThreadID tid)
1177{
1178 if (fromIEW->iewInfo[tid].usedIQ)
1179 freeEntries[tid].iqEntries = fromIEW->iewInfo[tid].freeIQEntries;
1180
1181 if (fromIEW->iewInfo[tid].usedLSQ)
1182 freeEntries[tid].lsqEntries = fromIEW->iewInfo[tid].freeLSQEntries;
1183
1184 if (fromCommit->commitInfo[tid].usedROB) {
1185 freeEntries[tid].robEntries =
1186 fromCommit->commitInfo[tid].freeROBEntries;
1187 emptyROB[tid] = fromCommit->commitInfo[tid].emptyROB;
1188 }
1189
1190 DPRINTF(Rename, "[tid:%i]: Free IQ: %i, Free ROB: %i, Free LSQ: %i\n",
1191 tid,
1192 freeEntries[tid].iqEntries,
1193 freeEntries[tid].robEntries,
1194 freeEntries[tid].lsqEntries);
1195
1196 DPRINTF(Rename, "[tid:%i]: %i instructions not yet in ROB\n",
1197 tid, instsInProgress[tid]);
1198}
1199
1200template <class Impl>
1201bool
1202DefaultRename<Impl>::checkSignalsAndUpdate(ThreadID tid)
1203{
1204 // Check if there's a squash signal, squash if there is
1205 // Check stall signals, block if necessary.
1206 // If status was blocked
1207 // check if stall conditions have passed
1208 // if so then go to unblocking
1209 // If status was Squashing
1210 // check if squashing is not high. Switch to running this cycle.
1211 // If status was serialize stall
1212 // check if ROB is empty and no insts are in flight to the ROB
1213
1214 readFreeEntries(tid);
1215 readStallSignals(tid);
1216
1217 if (fromCommit->commitInfo[tid].squash) {
1218 DPRINTF(Rename, "[tid:%u]: Squashing instructions due to squash from "
1219 "commit.\n", tid);
1220
1221 squash(fromCommit->commitInfo[tid].doneSeqNum, tid);
1222
1223 return true;
1224 }
1225
1226 if (fromCommit->commitInfo[tid].robSquashing) {
1227 DPRINTF(Rename, "[tid:%u]: ROB is still squashing.\n", tid);
1228
1229 renameStatus[tid] = Squashing;
1230
1231 return true;
1232 }
1233
1234 if (checkStall(tid)) {
1235 return block(tid);
1236 }
1237
1238 if (renameStatus[tid] == Blocked) {
1239 DPRINTF(Rename, "[tid:%u]: Done blocking, switching to unblocking.\n",
1240 tid);
1241
1242 renameStatus[tid] = Unblocking;
1243
1244 unblock(tid);
1245
1246 return true;
1247 }
1248
1249 if (renameStatus[tid] == Squashing) {
1250 // Switch status to running if rename isn't being told to block or
1251 // squash this cycle.
1252 if (resumeSerialize) {
1253 DPRINTF(Rename, "[tid:%u]: Done squashing, switching to serialize.\n",
1254 tid);
1255
1256 renameStatus[tid] = SerializeStall;
1257 return true;
1258 } else if (resumeUnblocking) {
1259 DPRINTF(Rename, "[tid:%u]: Done squashing, switching to unblocking.\n",
1260 tid);
1261 renameStatus[tid] = Unblocking;
1262 return true;
1263 } else {
1264 DPRINTF(Rename, "[tid:%u]: Done squashing, switching to running.\n",
1265 tid);
1266
1267 renameStatus[tid] = Running;
1268 return false;
1269 }
1270 }
1271
1272 if (renameStatus[tid] == SerializeStall) {
1273 // Stall ends once the ROB is free.
1274 DPRINTF(Rename, "[tid:%u]: Done with serialize stall, switching to "
1275 "unblocking.\n", tid);
1276
1277 DynInstPtr serial_inst = serializeInst[tid];
1278
1279 renameStatus[tid] = Unblocking;
1280
1281 unblock(tid);
1282
1283 DPRINTF(Rename, "[tid:%u]: Processing instruction [%lli] with "
1284 "PC %s.\n", tid, serial_inst->seqNum, serial_inst->pcState());
1285
1286 // Put instruction into queue here.
1287 serial_inst->clearSerializeBefore();
1288
1289 if (!skidBuffer[tid].empty()) {
1290 skidBuffer[tid].push_front(serial_inst);
1291 } else {
1292 insts[tid].push_front(serial_inst);
1293 }
1294
1295 DPRINTF(Rename, "[tid:%u]: Instruction must be processed by rename."
1296 " Adding to front of list.\n", tid);
1297
1298 serializeInst[tid] = NULL;
1299
1300 return true;
1301 }
1302
1303 // If we've reached this point, we have not gotten any signals that
1304 // cause rename to change its status. Rename remains the same as before.
1305 return false;
1306}
1307
1308template<class Impl>
1309void
1310DefaultRename<Impl>::serializeAfter(InstQueue &inst_list, ThreadID tid)
1311{
1312 if (inst_list.empty()) {
1313 // Mark a bit to say that I must serialize on the next instruction.
1314 serializeOnNextInst[tid] = true;
1315 return;
1316 }
1317
1318 // Set the next instruction as serializing.
1319 inst_list.front()->setSerializeBefore();
1320}
1321
1322template <class Impl>
1323inline void
1324DefaultRename<Impl>::incrFullStat(const FullSource &source)
1325{
1326 switch (source) {
1327 case ROB:
1328 ++renameROBFullEvents;
1329 break;
1330 case IQ:
1331 ++renameIQFullEvents;
1332 break;
1333 case LSQ:
1334 ++renameLSQFullEvents;
1335 break;
1336 default:
1337 panic("Rename full stall stat should be incremented for a reason!");
1338 break;
1339 }
1340}
1341
1342template <class Impl>
1343void
1344DefaultRename<Impl>::dumpHistory()
1345{
1346 typename std::list<RenameHistory>::iterator buf_it;
1347
1348 for (ThreadID tid = 0; tid < numThreads; tid++) {
1349
1350 buf_it = historyBuffer[tid].begin();
1351
1352 while (buf_it != historyBuffer[tid].end()) {
1353 cprintf("Seq num: %i\nArch reg: %i New phys reg: %i Old phys "
1354 "reg: %i\n", (*buf_it).instSeqNum, (int)(*buf_it).archReg,
1355 (int)(*buf_it).newPhysReg, (int)(*buf_it).prevPhysReg);
1356
1357 buf_it++;
1358 }
1359 }
1360}
742 }
743}
744
745template<class Impl>
746bool
747DefaultRename<Impl>::skidsEmpty()
748{
749 list<ThreadID>::iterator threads = activeThreads->begin();
750 list<ThreadID>::iterator end = activeThreads->end();
751
752 while (threads != end) {
753 ThreadID tid = *threads++;
754
755 if (!skidBuffer[tid].empty())
756 return false;
757 }
758
759 return true;
760}
761
762template<class Impl>
763void
764DefaultRename<Impl>::updateStatus()
765{
766 bool any_unblocking = false;
767
768 list<ThreadID>::iterator threads = activeThreads->begin();
769 list<ThreadID>::iterator end = activeThreads->end();
770
771 while (threads != end) {
772 ThreadID tid = *threads++;
773
774 if (renameStatus[tid] == Unblocking) {
775 any_unblocking = true;
776 break;
777 }
778 }
779
780 // Rename will have activity if it's unblocking.
781 if (any_unblocking) {
782 if (_status == Inactive) {
783 _status = Active;
784
785 DPRINTF(Activity, "Activating stage.\n");
786
787 cpu->activateStage(O3CPU::RenameIdx);
788 }
789 } else {
790 // If it's not unblocking, then rename will not have any internal
791 // activity. Switch it to inactive.
792 if (_status == Active) {
793 _status = Inactive;
794 DPRINTF(Activity, "Deactivating stage.\n");
795
796 cpu->deactivateStage(O3CPU::RenameIdx);
797 }
798 }
799}
800
801template <class Impl>
802bool
803DefaultRename<Impl>::block(ThreadID tid)
804{
805 DPRINTF(Rename, "[tid:%u]: Blocking.\n", tid);
806
807 // Add the current inputs onto the skid buffer, so they can be
808 // reprocessed when this stage unblocks.
809 skidInsert(tid);
810
811 // Only signal backwards to block if the previous stages do not think
812 // rename is already blocked.
813 if (renameStatus[tid] != Blocked) {
814 // If resumeUnblocking is set, we unblocked during the squash,
815 // but now we're have unblocking status. We need to tell earlier
816 // stages to block.
817 if (resumeUnblocking || renameStatus[tid] != Unblocking) {
818 toDecode->renameBlock[tid] = true;
819 toDecode->renameUnblock[tid] = false;
820 wroteToTimeBuffer = true;
821 }
822
823 // Rename can not go from SerializeStall to Blocked, otherwise
824 // it would not know to complete the serialize stall.
825 if (renameStatus[tid] != SerializeStall) {
826 // Set status to Blocked.
827 renameStatus[tid] = Blocked;
828 return true;
829 }
830 }
831
832 return false;
833}
834
835template <class Impl>
836bool
837DefaultRename<Impl>::unblock(ThreadID tid)
838{
839 DPRINTF(Rename, "[tid:%u]: Trying to unblock.\n", tid);
840
841 // Rename is done unblocking if the skid buffer is empty.
842 if (skidBuffer[tid].empty() && renameStatus[tid] != SerializeStall) {
843
844 DPRINTF(Rename, "[tid:%u]: Done unblocking.\n", tid);
845
846 toDecode->renameUnblock[tid] = true;
847 wroteToTimeBuffer = true;
848
849 renameStatus[tid] = Running;
850 return true;
851 }
852
853 return false;
854}
855
856template <class Impl>
857void
858DefaultRename<Impl>::doSquash(const InstSeqNum &squashed_seq_num, ThreadID tid)
859{
860 typename std::list<RenameHistory>::iterator hb_it =
861 historyBuffer[tid].begin();
862
863 // After a syscall squashes everything, the history buffer may be empty
864 // but the ROB may still be squashing instructions.
865 if (historyBuffer[tid].empty()) {
866 return;
867 }
868
869 // Go through the most recent instructions, undoing the mappings
870 // they did and freeing up the registers.
871 while (!historyBuffer[tid].empty() &&
872 (*hb_it).instSeqNum > squashed_seq_num) {
873 assert(hb_it != historyBuffer[tid].end());
874
875 DPRINTF(Rename, "[tid:%u]: Removing history entry with sequence "
876 "number %i.\n", tid, (*hb_it).instSeqNum);
877
878 // Tell the rename map to set the architected register to the
879 // previous physical register that it was renamed to.
880 renameMap[tid]->setEntry(hb_it->archReg, hb_it->prevPhysReg);
881
882 // Put the renamed physical register back on the free list.
883 freeList->addReg(hb_it->newPhysReg);
884
885 // Be sure to mark its register as ready if it's a misc register.
886 if (hb_it->newPhysReg >= maxPhysicalRegs) {
887 scoreboard->setReg(hb_it->newPhysReg);
888 }
889
890 historyBuffer[tid].erase(hb_it++);
891
892 ++renameUndoneMaps;
893 }
894}
895
896template<class Impl>
897void
898DefaultRename<Impl>::removeFromHistory(InstSeqNum inst_seq_num, ThreadID tid)
899{
900 DPRINTF(Rename, "[tid:%u]: Removing a committed instruction from the "
901 "history buffer %u (size=%i), until [sn:%lli].\n",
902 tid, tid, historyBuffer[tid].size(), inst_seq_num);
903
904 typename std::list<RenameHistory>::iterator hb_it =
905 historyBuffer[tid].end();
906
907 --hb_it;
908
909 if (historyBuffer[tid].empty()) {
910 DPRINTF(Rename, "[tid:%u]: History buffer is empty.\n", tid);
911 return;
912 } else if (hb_it->instSeqNum > inst_seq_num) {
913 DPRINTF(Rename, "[tid:%u]: Old sequence number encountered. Ensure "
914 "that a syscall happened recently.\n", tid);
915 return;
916 }
917
918 // Commit all the renames up until (and including) the committed sequence
919 // number. Some or even all of the committed instructions may not have
920 // rename histories if they did not have destination registers that were
921 // renamed.
922 while (!historyBuffer[tid].empty() &&
923 hb_it != historyBuffer[tid].end() &&
924 (*hb_it).instSeqNum <= inst_seq_num) {
925
926 DPRINTF(Rename, "[tid:%u]: Freeing up older rename of reg %i, "
927 "[sn:%lli].\n",
928 tid, (*hb_it).prevPhysReg, (*hb_it).instSeqNum);
929
930 freeList->addReg((*hb_it).prevPhysReg);
931 ++renameCommittedMaps;
932
933 historyBuffer[tid].erase(hb_it--);
934 }
935}
936
937template <class Impl>
938inline void
939DefaultRename<Impl>::renameSrcRegs(DynInstPtr &inst, ThreadID tid)
940{
941 assert(renameMap[tid] != 0);
942
943 unsigned num_src_regs = inst->numSrcRegs();
944
945 // Get the architectual register numbers from the source and
946 // destination operands, and redirect them to the right register.
947 // Will need to mark dependencies though.
948 for (int src_idx = 0; src_idx < num_src_regs; src_idx++) {
949 RegIndex src_reg = inst->srcRegIdx(src_idx);
950 RegIndex flat_src_reg = src_reg;
951 if (src_reg < TheISA::FP_Base_DepTag) {
952 flat_src_reg = inst->tcBase()->flattenIntIndex(src_reg);
953 DPRINTF(Rename, "Flattening index %d to %d.\n",
954 (int)src_reg, (int)flat_src_reg);
955 } else if (src_reg < TheISA::Ctrl_Base_DepTag) {
956 src_reg = src_reg - TheISA::FP_Base_DepTag;
957 flat_src_reg = inst->tcBase()->flattenFloatIndex(src_reg);
958 DPRINTF(Rename, "Flattening index %d to %d.\n",
959 (int)src_reg, (int)flat_src_reg);
960 flat_src_reg += TheISA::NumIntRegs;
961 } else if (src_reg < TheISA::Max_DepTag) {
962 flat_src_reg = src_reg - TheISA::Ctrl_Base_DepTag +
963 TheISA::NumFloatRegs + TheISA::NumIntRegs;
964 DPRINTF(Rename, "Adjusting reg index from %d to %d.\n",
965 src_reg, flat_src_reg);
966 } else {
967 panic("Reg index is out of bound: %d.", src_reg);
968 }
969
970 // Look up the source registers to get the phys. register they've
971 // been renamed to, and set the sources to those registers.
972 PhysRegIndex renamed_reg = renameMap[tid]->lookup(flat_src_reg);
973
974 DPRINTF(Rename, "[tid:%u]: Looking up arch reg %i, got "
975 "physical reg %i.\n", tid, (int)flat_src_reg,
976 (int)renamed_reg);
977
978 inst->renameSrcReg(src_idx, renamed_reg);
979
980 // See if the register is ready or not.
981 if (scoreboard->getReg(renamed_reg) == true) {
982 DPRINTF(Rename, "[tid:%u]: Register %d is ready.\n",
983 tid, renamed_reg);
984
985 inst->markSrcRegReady(src_idx);
986 } else {
987 DPRINTF(Rename, "[tid:%u]: Register %d is not ready.\n",
988 tid, renamed_reg);
989 }
990
991 ++renameRenameLookups;
992 inst->isFloating() ? fpRenameLookups++ : intRenameLookups++;
993 }
994}
995
996template <class Impl>
997inline void
998DefaultRename<Impl>::renameDestRegs(DynInstPtr &inst, ThreadID tid)
999{
1000 typename RenameMap::RenameInfo rename_result;
1001
1002 unsigned num_dest_regs = inst->numDestRegs();
1003
1004 // Rename the destination registers.
1005 for (int dest_idx = 0; dest_idx < num_dest_regs; dest_idx++) {
1006 RegIndex dest_reg = inst->destRegIdx(dest_idx);
1007 RegIndex flat_dest_reg = dest_reg;
1008 if (dest_reg < TheISA::FP_Base_DepTag) {
1009 // Integer registers are flattened.
1010 flat_dest_reg = inst->tcBase()->flattenIntIndex(dest_reg);
1011 DPRINTF(Rename, "Flattening index %d to %d.\n",
1012 (int)dest_reg, (int)flat_dest_reg);
1013 } else if (dest_reg < TheISA::Ctrl_Base_DepTag) {
1014 dest_reg = dest_reg - TheISA::FP_Base_DepTag;
1015 flat_dest_reg = inst->tcBase()->flattenFloatIndex(dest_reg);
1016 DPRINTF(Rename, "Flattening index %d to %d.\n",
1017 (int)dest_reg, (int)flat_dest_reg);
1018 flat_dest_reg += TheISA::NumIntRegs;
1019 } else if (dest_reg < TheISA::Max_DepTag) {
1020 // Floating point and Miscellaneous registers need their indexes
1021 // adjusted to account for the expanded number of flattened int regs.
1022 flat_dest_reg = dest_reg - TheISA::Ctrl_Base_DepTag +
1023 TheISA::NumIntRegs + TheISA::NumFloatRegs;
1024 DPRINTF(Rename, "Adjusting reg index from %d to %d.\n",
1025 dest_reg, flat_dest_reg);
1026 } else {
1027 panic("Reg index is out of bound: %d.", dest_reg);
1028 }
1029
1030 inst->flattenDestReg(dest_idx, flat_dest_reg);
1031
1032 // Get the physical register that the destination will be
1033 // renamed to.
1034 rename_result = renameMap[tid]->rename(flat_dest_reg);
1035
1036 //Mark Scoreboard entry as not ready
1037 if (dest_reg < TheISA::Ctrl_Base_DepTag)
1038 scoreboard->unsetReg(rename_result.first);
1039
1040 DPRINTF(Rename, "[tid:%u]: Renaming arch reg %i to physical "
1041 "reg %i.\n", tid, (int)flat_dest_reg,
1042 (int)rename_result.first);
1043
1044 // Record the rename information so that a history can be kept.
1045 RenameHistory hb_entry(inst->seqNum, flat_dest_reg,
1046 rename_result.first,
1047 rename_result.second);
1048
1049 historyBuffer[tid].push_front(hb_entry);
1050
1051 DPRINTF(Rename, "[tid:%u]: Adding instruction to history buffer "
1052 "(size=%i), [sn:%lli].\n",tid,
1053 historyBuffer[tid].size(),
1054 (*historyBuffer[tid].begin()).instSeqNum);
1055
1056 // Tell the instruction to rename the appropriate destination
1057 // register (dest_idx) to the new physical register
1058 // (rename_result.first), and record the previous physical
1059 // register that the same logical register was renamed to
1060 // (rename_result.second).
1061 inst->renameDestReg(dest_idx,
1062 rename_result.first,
1063 rename_result.second);
1064
1065 ++renameRenamedOperands;
1066 }
1067}
1068
1069template <class Impl>
1070inline int
1071DefaultRename<Impl>::calcFreeROBEntries(ThreadID tid)
1072{
1073 int num_free = freeEntries[tid].robEntries -
1074 (instsInProgress[tid] - fromIEW->iewInfo[tid].dispatched);
1075
1076 //DPRINTF(Rename,"[tid:%i]: %i rob free\n",tid,num_free);
1077
1078 return num_free;
1079}
1080
1081template <class Impl>
1082inline int
1083DefaultRename<Impl>::calcFreeIQEntries(ThreadID tid)
1084{
1085 int num_free = freeEntries[tid].iqEntries -
1086 (instsInProgress[tid] - fromIEW->iewInfo[tid].dispatched);
1087
1088 //DPRINTF(Rename,"[tid:%i]: %i iq free\n",tid,num_free);
1089
1090 return num_free;
1091}
1092
1093template <class Impl>
1094inline int
1095DefaultRename<Impl>::calcFreeLSQEntries(ThreadID tid)
1096{
1097 int num_free = freeEntries[tid].lsqEntries -
1098 (instsInProgress[tid] - fromIEW->iewInfo[tid].dispatchedToLSQ);
1099
1100 //DPRINTF(Rename,"[tid:%i]: %i lsq free\n",tid,num_free);
1101
1102 return num_free;
1103}
1104
1105template <class Impl>
1106unsigned
1107DefaultRename<Impl>::validInsts()
1108{
1109 unsigned inst_count = 0;
1110
1111 for (int i=0; i<fromDecode->size; i++) {
1112 if (!fromDecode->insts[i]->isSquashed())
1113 inst_count++;
1114 }
1115
1116 return inst_count;
1117}
1118
1119template <class Impl>
1120void
1121DefaultRename<Impl>::readStallSignals(ThreadID tid)
1122{
1123 if (fromIEW->iewBlock[tid]) {
1124 stalls[tid].iew = true;
1125 }
1126
1127 if (fromIEW->iewUnblock[tid]) {
1128 assert(stalls[tid].iew);
1129 stalls[tid].iew = false;
1130 }
1131
1132 if (fromCommit->commitBlock[tid]) {
1133 stalls[tid].commit = true;
1134 }
1135
1136 if (fromCommit->commitUnblock[tid]) {
1137 assert(stalls[tid].commit);
1138 stalls[tid].commit = false;
1139 }
1140}
1141
1142template <class Impl>
1143bool
1144DefaultRename<Impl>::checkStall(ThreadID tid)
1145{
1146 bool ret_val = false;
1147
1148 if (stalls[tid].iew) {
1149 DPRINTF(Rename,"[tid:%i]: Stall from IEW stage detected.\n", tid);
1150 ret_val = true;
1151 } else if (stalls[tid].commit) {
1152 DPRINTF(Rename,"[tid:%i]: Stall from Commit stage detected.\n", tid);
1153 ret_val = true;
1154 } else if (calcFreeROBEntries(tid) <= 0) {
1155 DPRINTF(Rename,"[tid:%i]: Stall: ROB has 0 free entries.\n", tid);
1156 ret_val = true;
1157 } else if (calcFreeIQEntries(tid) <= 0) {
1158 DPRINTF(Rename,"[tid:%i]: Stall: IQ has 0 free entries.\n", tid);
1159 ret_val = true;
1160 } else if (calcFreeLSQEntries(tid) <= 0) {
1161 DPRINTF(Rename,"[tid:%i]: Stall: LSQ has 0 free entries.\n", tid);
1162 ret_val = true;
1163 } else if (renameMap[tid]->numFreeEntries() <= 0) {
1164 DPRINTF(Rename,"[tid:%i]: Stall: RenameMap has 0 free entries.\n", tid);
1165 ret_val = true;
1166 } else if (renameStatus[tid] == SerializeStall &&
1167 (!emptyROB[tid] || instsInProgress[tid])) {
1168 DPRINTF(Rename,"[tid:%i]: Stall: Serialize stall and ROB is not "
1169 "empty.\n",
1170 tid);
1171 ret_val = true;
1172 }
1173
1174 return ret_val;
1175}
1176
1177template <class Impl>
1178void
1179DefaultRename<Impl>::readFreeEntries(ThreadID tid)
1180{
1181 if (fromIEW->iewInfo[tid].usedIQ)
1182 freeEntries[tid].iqEntries = fromIEW->iewInfo[tid].freeIQEntries;
1183
1184 if (fromIEW->iewInfo[tid].usedLSQ)
1185 freeEntries[tid].lsqEntries = fromIEW->iewInfo[tid].freeLSQEntries;
1186
1187 if (fromCommit->commitInfo[tid].usedROB) {
1188 freeEntries[tid].robEntries =
1189 fromCommit->commitInfo[tid].freeROBEntries;
1190 emptyROB[tid] = fromCommit->commitInfo[tid].emptyROB;
1191 }
1192
1193 DPRINTF(Rename, "[tid:%i]: Free IQ: %i, Free ROB: %i, Free LSQ: %i\n",
1194 tid,
1195 freeEntries[tid].iqEntries,
1196 freeEntries[tid].robEntries,
1197 freeEntries[tid].lsqEntries);
1198
1199 DPRINTF(Rename, "[tid:%i]: %i instructions not yet in ROB\n",
1200 tid, instsInProgress[tid]);
1201}
1202
1203template <class Impl>
1204bool
1205DefaultRename<Impl>::checkSignalsAndUpdate(ThreadID tid)
1206{
1207 // Check if there's a squash signal, squash if there is
1208 // Check stall signals, block if necessary.
1209 // If status was blocked
1210 // check if stall conditions have passed
1211 // if so then go to unblocking
1212 // If status was Squashing
1213 // check if squashing is not high. Switch to running this cycle.
1214 // If status was serialize stall
1215 // check if ROB is empty and no insts are in flight to the ROB
1216
1217 readFreeEntries(tid);
1218 readStallSignals(tid);
1219
1220 if (fromCommit->commitInfo[tid].squash) {
1221 DPRINTF(Rename, "[tid:%u]: Squashing instructions due to squash from "
1222 "commit.\n", tid);
1223
1224 squash(fromCommit->commitInfo[tid].doneSeqNum, tid);
1225
1226 return true;
1227 }
1228
1229 if (fromCommit->commitInfo[tid].robSquashing) {
1230 DPRINTF(Rename, "[tid:%u]: ROB is still squashing.\n", tid);
1231
1232 renameStatus[tid] = Squashing;
1233
1234 return true;
1235 }
1236
1237 if (checkStall(tid)) {
1238 return block(tid);
1239 }
1240
1241 if (renameStatus[tid] == Blocked) {
1242 DPRINTF(Rename, "[tid:%u]: Done blocking, switching to unblocking.\n",
1243 tid);
1244
1245 renameStatus[tid] = Unblocking;
1246
1247 unblock(tid);
1248
1249 return true;
1250 }
1251
1252 if (renameStatus[tid] == Squashing) {
1253 // Switch status to running if rename isn't being told to block or
1254 // squash this cycle.
1255 if (resumeSerialize) {
1256 DPRINTF(Rename, "[tid:%u]: Done squashing, switching to serialize.\n",
1257 tid);
1258
1259 renameStatus[tid] = SerializeStall;
1260 return true;
1261 } else if (resumeUnblocking) {
1262 DPRINTF(Rename, "[tid:%u]: Done squashing, switching to unblocking.\n",
1263 tid);
1264 renameStatus[tid] = Unblocking;
1265 return true;
1266 } else {
1267 DPRINTF(Rename, "[tid:%u]: Done squashing, switching to running.\n",
1268 tid);
1269
1270 renameStatus[tid] = Running;
1271 return false;
1272 }
1273 }
1274
1275 if (renameStatus[tid] == SerializeStall) {
1276 // Stall ends once the ROB is free.
1277 DPRINTF(Rename, "[tid:%u]: Done with serialize stall, switching to "
1278 "unblocking.\n", tid);
1279
1280 DynInstPtr serial_inst = serializeInst[tid];
1281
1282 renameStatus[tid] = Unblocking;
1283
1284 unblock(tid);
1285
1286 DPRINTF(Rename, "[tid:%u]: Processing instruction [%lli] with "
1287 "PC %s.\n", tid, serial_inst->seqNum, serial_inst->pcState());
1288
1289 // Put instruction into queue here.
1290 serial_inst->clearSerializeBefore();
1291
1292 if (!skidBuffer[tid].empty()) {
1293 skidBuffer[tid].push_front(serial_inst);
1294 } else {
1295 insts[tid].push_front(serial_inst);
1296 }
1297
1298 DPRINTF(Rename, "[tid:%u]: Instruction must be processed by rename."
1299 " Adding to front of list.\n", tid);
1300
1301 serializeInst[tid] = NULL;
1302
1303 return true;
1304 }
1305
1306 // If we've reached this point, we have not gotten any signals that
1307 // cause rename to change its status. Rename remains the same as before.
1308 return false;
1309}
1310
1311template<class Impl>
1312void
1313DefaultRename<Impl>::serializeAfter(InstQueue &inst_list, ThreadID tid)
1314{
1315 if (inst_list.empty()) {
1316 // Mark a bit to say that I must serialize on the next instruction.
1317 serializeOnNextInst[tid] = true;
1318 return;
1319 }
1320
1321 // Set the next instruction as serializing.
1322 inst_list.front()->setSerializeBefore();
1323}
1324
1325template <class Impl>
1326inline void
1327DefaultRename<Impl>::incrFullStat(const FullSource &source)
1328{
1329 switch (source) {
1330 case ROB:
1331 ++renameROBFullEvents;
1332 break;
1333 case IQ:
1334 ++renameIQFullEvents;
1335 break;
1336 case LSQ:
1337 ++renameLSQFullEvents;
1338 break;
1339 default:
1340 panic("Rename full stall stat should be incremented for a reason!");
1341 break;
1342 }
1343}
1344
1345template <class Impl>
1346void
1347DefaultRename<Impl>::dumpHistory()
1348{
1349 typename std::list<RenameHistory>::iterator buf_it;
1350
1351 for (ThreadID tid = 0; tid < numThreads; tid++) {
1352
1353 buf_it = historyBuffer[tid].begin();
1354
1355 while (buf_it != historyBuffer[tid].end()) {
1356 cprintf("Seq num: %i\nArch reg: %i New phys reg: %i Old phys "
1357 "reg: %i\n", (*buf_it).instSeqNum, (int)(*buf_it).archReg,
1358 (int)(*buf_it).newPhysReg, (int)(*buf_it).prevPhysReg);
1359
1360 buf_it++;
1361 }
1362 }
1363}