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