Deleted Added
sdiff udiff text old ( 9444:ab47fe7f03f0 ) new ( 9527:68154bc0e0ea )
full compact
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 "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
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);
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}