4035667ebee97ed52293bc8c7171e8232a3330e8
[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 template <class Impl>
57 DefaultRename<Impl>::DefaultRename(O3CPU *_cpu, const 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 stats(_cpu)
66 {
67 if (renameWidth > Impl::MaxWidth)
68 fatal("renameWidth (%d) is larger than compiled limit (%d),\n"
69 "\tincrease MaxWidth in src/cpu/o3/impl.hh\n",
70 renameWidth, static_cast<int>(Impl::MaxWidth));
71
72 // @todo: Make into a parameter.
73 skidBufferMax = (decodeToRenameDelay + 1) * params.decodeWidth;
74 for (uint32_t tid = 0; tid < Impl::MaxThreads; tid++) {
75 renameStatus[tid] = Idle;
76 renameMap[tid] = nullptr;
77 instsInProgress[tid] = 0;
78 loadsInProgress[tid] = 0;
79 storesInProgress[tid] = 0;
80 freeEntries[tid] = {0, 0, 0, 0};
81 emptyROB[tid] = true;
82 stalls[tid] = {false, false};
83 serializeInst[tid] = nullptr;
84 serializeOnNextInst[tid] = false;
85 }
86 }
87
88 template <class Impl>
89 std::string
90 DefaultRename<Impl>::name() const
91 {
92 return cpu->name() + ".rename";
93 }
94
95 template <class Impl>
96 DefaultRename<Impl>::RenameStats::RenameStats(Stats::Group *parent)
97 : Stats::Group(parent, "rename"),
98 ADD_STAT(squashCycles, "Number of cycles rename is squashing"),
99 ADD_STAT(idleCycles, "Number of cycles rename is idle"),
100 ADD_STAT(blockCycles, "Number of cycles rename is blocking"),
101 ADD_STAT(serializeStallCycles, "count of cycles rename stalled"
102 "for serializing inst"),
103 ADD_STAT(runCycles, "Number of cycles rename is running"),
104 ADD_STAT(unblockCycles, "Number of cycles rename is unblocking"),
105 ADD_STAT(renamedInsts, "Number of instructions processed by"
106 " rename"),
107 ADD_STAT(squashedInsts, "Number of squashed instructions"
108 " processed by rename"),
109 ADD_STAT(ROBFullEvents, "Number of times rename has blocked"
110 " due to ROB full"),
111 ADD_STAT(IQFullEvents, "Number of times rename has blocked due"
112 " to IQ full"),
113 ADD_STAT(LQFullEvents, "Number of times rename has blocked due"
114 " to LQ full" ),
115 ADD_STAT(SQFullEvents, "Number of times rename has blocked due"
116 " to SQ full"),
117 ADD_STAT(fullRegistersEvents, "Number of times there has been no"
118 " free registers"),
119 ADD_STAT(renamedOperands, "Number of destination operands rename"
120 " has renamed"),
121 ADD_STAT(lookups, "Number of register rename lookups that"
122 " rename has made"),
123 ADD_STAT(intLookups, "Number of integer rename lookups"),
124 ADD_STAT(fpLookups, "Number of floating rename lookups"),
125 ADD_STAT(vecLookups, "Number of vector rename lookups"),
126 ADD_STAT(vecPredLookups, "Number of vector predicate rename"
127 " lookups"),
128 ADD_STAT(committedMaps, "Number of HB maps that are committed"),
129 ADD_STAT(undoneMaps, "Number of HB maps that are undone due to"
130 " squashing"),
131 ADD_STAT(serializing, "count of serializing insts renamed" ),
132 ADD_STAT(tempSerializing, "count of temporary serializing insts"
133 " renamed"),
134 ADD_STAT(skidInsts, "count of insts added to the skid buffer")
135 {
136 squashCycles.prereq(squashCycles);
137 idleCycles.prereq(idleCycles);
138 blockCycles.prereq(blockCycles);
139 serializeStallCycles.flags(Stats::total);
140 runCycles.prereq(idleCycles);
141 unblockCycles.prereq(unblockCycles);
142
143 renamedInsts.prereq(renamedInsts);
144 squashedInsts.prereq(squashedInsts);
145
146 ROBFullEvents.prereq(ROBFullEvents);
147 IQFullEvents.prereq(IQFullEvents);
148 LQFullEvents.prereq(LQFullEvents);
149 SQFullEvents.prereq(SQFullEvents);
150 fullRegistersEvents.prereq(fullRegistersEvents);
151
152 renamedOperands.prereq(renamedOperands);
153 lookups.prereq(lookups);
154 intLookups.prereq(intLookups);
155 fpLookups.prereq(fpLookups);
156 vecLookups.prereq(vecLookups);
157 vecPredLookups.prereq(vecPredLookups);
158
159 committedMaps.prereq(committedMaps);
160 undoneMaps.prereq(undoneMaps);
161 serializing.flags(Stats::total);
162 tempSerializing.flags(Stats::total);
163 skidInsts.flags(Stats::total);
164 }
165
166 template <class Impl>
167 void
168 DefaultRename<Impl>::regProbePoints()
169 {
170 ppRename = new ProbePointArg<DynInstPtr>(cpu->getProbeManager(), "Rename");
171 ppSquashInRename = new ProbePointArg<SeqNumRegPair>(cpu->getProbeManager(),
172 "SquashInRename");
173 }
174
175 template <class Impl>
176 void
177 DefaultRename<Impl>::setTimeBuffer(TimeBuffer<TimeStruct> *tb_ptr)
178 {
179 timeBuffer = tb_ptr;
180
181 // Setup wire to read information from time buffer, from IEW stage.
182 fromIEW = timeBuffer->getWire(-iewToRenameDelay);
183
184 // Setup wire to read infromation from time buffer, from commit stage.
185 fromCommit = timeBuffer->getWire(-commitToRenameDelay);
186
187 // Setup wire to write information to previous stages.
188 toDecode = timeBuffer->getWire(0);
189 }
190
191 template <class Impl>
192 void
193 DefaultRename<Impl>::setRenameQueue(TimeBuffer<RenameStruct> *rq_ptr)
194 {
195 renameQueue = rq_ptr;
196
197 // Setup wire to write information to future stages.
198 toIEW = renameQueue->getWire(0);
199 }
200
201 template <class Impl>
202 void
203 DefaultRename<Impl>::setDecodeQueue(TimeBuffer<DecodeStruct> *dq_ptr)
204 {
205 decodeQueue = dq_ptr;
206
207 // Setup wire to get information from decode.
208 fromDecode = decodeQueue->getWire(-decodeToRenameDelay);
209 }
210
211 template <class Impl>
212 void
213 DefaultRename<Impl>::startupStage()
214 {
215 resetStage();
216 }
217
218 template <class Impl>
219 void
220 DefaultRename<Impl>::clearStates(ThreadID tid)
221 {
222 renameStatus[tid] = Idle;
223
224 freeEntries[tid].iqEntries = iew_ptr->instQueue.numFreeEntries(tid);
225 freeEntries[tid].lqEntries = iew_ptr->ldstQueue.numFreeLoadEntries(tid);
226 freeEntries[tid].sqEntries = iew_ptr->ldstQueue.numFreeStoreEntries(tid);
227 freeEntries[tid].robEntries = commit_ptr->numROBFreeEntries(tid);
228 emptyROB[tid] = true;
229
230 stalls[tid].iew = false;
231 serializeInst[tid] = NULL;
232
233 instsInProgress[tid] = 0;
234 loadsInProgress[tid] = 0;
235 storesInProgress[tid] = 0;
236
237 serializeOnNextInst[tid] = false;
238 }
239
240 template <class Impl>
241 void
242 DefaultRename<Impl>::resetStage()
243 {
244 _status = Inactive;
245
246 resumeSerialize = false;
247 resumeUnblocking = false;
248
249 // Grab the number of free entries directly from the stages.
250 for (ThreadID tid = 0; tid < numThreads; tid++) {
251 renameStatus[tid] = Idle;
252
253 freeEntries[tid].iqEntries = iew_ptr->instQueue.numFreeEntries(tid);
254 freeEntries[tid].lqEntries = iew_ptr->ldstQueue.numFreeLoadEntries(tid);
255 freeEntries[tid].sqEntries = iew_ptr->ldstQueue.numFreeStoreEntries(tid);
256 freeEntries[tid].robEntries = commit_ptr->numROBFreeEntries(tid);
257 emptyROB[tid] = true;
258
259 stalls[tid].iew = false;
260 serializeInst[tid] = NULL;
261
262 instsInProgress[tid] = 0;
263 loadsInProgress[tid] = 0;
264 storesInProgress[tid] = 0;
265
266 serializeOnNextInst[tid] = false;
267 }
268 }
269
270 template<class Impl>
271 void
272 DefaultRename<Impl>::setActiveThreads(std::list<ThreadID> *at_ptr)
273 {
274 activeThreads = at_ptr;
275 }
276
277
278 template <class Impl>
279 void
280 DefaultRename<Impl>::setRenameMap(RenameMap rm_ptr[])
281 {
282 for (ThreadID tid = 0; tid < numThreads; tid++)
283 renameMap[tid] = &rm_ptr[tid];
284 }
285
286 template <class Impl>
287 void
288 DefaultRename<Impl>::setFreeList(FreeList *fl_ptr)
289 {
290 freeList = fl_ptr;
291 }
292
293 template<class Impl>
294 void
295 DefaultRename<Impl>::setScoreboard(Scoreboard *_scoreboard)
296 {
297 scoreboard = _scoreboard;
298 }
299
300 template <class Impl>
301 bool
302 DefaultRename<Impl>::isDrained() const
303 {
304 for (ThreadID tid = 0; tid < numThreads; tid++) {
305 if (instsInProgress[tid] != 0 ||
306 !historyBuffer[tid].empty() ||
307 !skidBuffer[tid].empty() ||
308 !insts[tid].empty() ||
309 (renameStatus[tid] != Idle && renameStatus[tid] != Running))
310 return false;
311 }
312 return true;
313 }
314
315 template <class Impl>
316 void
317 DefaultRename<Impl>::takeOverFrom()
318 {
319 resetStage();
320 }
321
322 template <class Impl>
323 void
324 DefaultRename<Impl>::drainSanityCheck() const
325 {
326 for (ThreadID tid = 0; tid < numThreads; tid++) {
327 assert(historyBuffer[tid].empty());
328 assert(insts[tid].empty());
329 assert(skidBuffer[tid].empty());
330 assert(instsInProgress[tid] == 0);
331 }
332 }
333
334 template <class Impl>
335 void
336 DefaultRename<Impl>::squash(const InstSeqNum &squash_seq_num, ThreadID tid)
337 {
338 DPRINTF(Rename, "[tid:%i] [squash sn:%llu] Squashing instructions.\n",
339 tid,squash_seq_num);
340
341 // Clear the stall signal if rename was blocked or unblocking before.
342 // If it still needs to block, the blocking should happen the next
343 // cycle and there should be space to hold everything due to the squash.
344 if (renameStatus[tid] == Blocked ||
345 renameStatus[tid] == Unblocking) {
346 toDecode->renameUnblock[tid] = 1;
347
348 resumeSerialize = false;
349 serializeInst[tid] = NULL;
350 } else if (renameStatus[tid] == SerializeStall) {
351 if (serializeInst[tid]->seqNum <= squash_seq_num) {
352 DPRINTF(Rename, "[tid:%i] [squash sn:%llu] "
353 "Rename will resume serializing after squash\n",
354 tid,squash_seq_num);
355 resumeSerialize = true;
356 assert(serializeInst[tid]);
357 } else {
358 resumeSerialize = false;
359 toDecode->renameUnblock[tid] = 1;
360
361 serializeInst[tid] = NULL;
362 }
363 }
364
365 // Set the status to Squashing.
366 renameStatus[tid] = Squashing;
367
368 // Squash any instructions from decode.
369 for (int i=0; i<fromDecode->size; i++) {
370 if (fromDecode->insts[i]->threadNumber == tid &&
371 fromDecode->insts[i]->seqNum > squash_seq_num) {
372 fromDecode->insts[i]->setSquashed();
373 wroteToTimeBuffer = true;
374 }
375
376 }
377
378 // Clear the instruction list and skid buffer in case they have any
379 // insts in them.
380 insts[tid].clear();
381
382 // Clear the skid buffer in case it has any data in it.
383 skidBuffer[tid].clear();
384
385 doSquash(squash_seq_num, tid);
386 }
387
388 template <class Impl>
389 void
390 DefaultRename<Impl>::tick()
391 {
392 wroteToTimeBuffer = false;
393
394 blockThisCycle = false;
395
396 bool status_change = false;
397
398 toIEWIndex = 0;
399
400 sortInsts();
401
402 std::list<ThreadID>::iterator threads = activeThreads->begin();
403 std::list<ThreadID>::iterator end = activeThreads->end();
404
405 // Check stall and squash signals.
406 while (threads != end) {
407 ThreadID tid = *threads++;
408
409 DPRINTF(Rename, "Processing [tid:%i]\n", tid);
410
411 status_change = checkSignalsAndUpdate(tid) || status_change;
412
413 rename(status_change, tid);
414 }
415
416 if (status_change) {
417 updateStatus();
418 }
419
420 if (wroteToTimeBuffer) {
421 DPRINTF(Activity, "Activity this cycle.\n");
422 cpu->activityThisCycle();
423 }
424
425 threads = activeThreads->begin();
426
427 while (threads != end) {
428 ThreadID tid = *threads++;
429
430 // If we committed this cycle then doneSeqNum will be > 0
431 if (fromCommit->commitInfo[tid].doneSeqNum != 0 &&
432 !fromCommit->commitInfo[tid].squash &&
433 renameStatus[tid] != Squashing) {
434
435 removeFromHistory(fromCommit->commitInfo[tid].doneSeqNum,
436 tid);
437 }
438 }
439
440 // @todo: make into updateProgress function
441 for (ThreadID tid = 0; tid < numThreads; tid++) {
442 instsInProgress[tid] -= fromIEW->iewInfo[tid].dispatched;
443 loadsInProgress[tid] -= fromIEW->iewInfo[tid].dispatchedToLQ;
444 storesInProgress[tid] -= fromIEW->iewInfo[tid].dispatchedToSQ;
445 assert(loadsInProgress[tid] >= 0);
446 assert(storesInProgress[tid] >= 0);
447 assert(instsInProgress[tid] >=0);
448 }
449
450 }
451
452 template<class Impl>
453 void
454 DefaultRename<Impl>::rename(bool &status_change, ThreadID tid)
455 {
456 // If status is Running or idle,
457 // call renameInsts()
458 // If status is Unblocking,
459 // buffer any instructions coming from decode
460 // continue trying to empty skid buffer
461 // check if stall conditions have passed
462
463 if (renameStatus[tid] == Blocked) {
464 ++stats.blockCycles;
465 } else if (renameStatus[tid] == Squashing) {
466 ++stats.squashCycles;
467 } else if (renameStatus[tid] == SerializeStall) {
468 ++stats.serializeStallCycles;
469 // If we are currently in SerializeStall and resumeSerialize
470 // was set, then that means that we are resuming serializing
471 // this cycle. Tell the previous stages to block.
472 if (resumeSerialize) {
473 resumeSerialize = false;
474 block(tid);
475 toDecode->renameUnblock[tid] = false;
476 }
477 } else if (renameStatus[tid] == Unblocking) {
478 if (resumeUnblocking) {
479 block(tid);
480 resumeUnblocking = false;
481 toDecode->renameUnblock[tid] = false;
482 }
483 }
484
485 if (renameStatus[tid] == Running ||
486 renameStatus[tid] == Idle) {
487 DPRINTF(Rename,
488 "[tid:%i] "
489 "Not blocked, so attempting to run stage.\n",
490 tid);
491
492 renameInsts(tid);
493 } else if (renameStatus[tid] == Unblocking) {
494 renameInsts(tid);
495
496 if (validInsts()) {
497 // Add the current inputs to the skid buffer so they can be
498 // reprocessed when this stage unblocks.
499 skidInsert(tid);
500 }
501
502 // If we switched over to blocking, then there's a potential for
503 // an overall status change.
504 status_change = unblock(tid) || status_change || blockThisCycle;
505 }
506 }
507
508 template <class Impl>
509 void
510 DefaultRename<Impl>::renameInsts(ThreadID tid)
511 {
512 // Instructions can be either in the skid buffer or the queue of
513 // instructions coming from decode, depending on the status.
514 int insts_available = renameStatus[tid] == Unblocking ?
515 skidBuffer[tid].size() : insts[tid].size();
516
517 // Check the decode queue to see if instructions are available.
518 // If there are no available instructions to rename, then do nothing.
519 if (insts_available == 0) {
520 DPRINTF(Rename, "[tid:%i] Nothing to do, breaking out early.\n",
521 tid);
522 // Should I change status to idle?
523 ++stats.idleCycles;
524 return;
525 } else if (renameStatus[tid] == Unblocking) {
526 ++stats.unblockCycles;
527 } else if (renameStatus[tid] == Running) {
528 ++stats.runCycles;
529 }
530
531 // Will have to do a different calculation for the number of free
532 // entries.
533 int free_rob_entries = calcFreeROBEntries(tid);
534 int free_iq_entries = calcFreeIQEntries(tid);
535 int min_free_entries = free_rob_entries;
536
537 FullSource source = ROB;
538
539 if (free_iq_entries < min_free_entries) {
540 min_free_entries = free_iq_entries;
541 source = IQ;
542 }
543
544 // Check if there's any space left.
545 if (min_free_entries <= 0) {
546 DPRINTF(Rename,
547 "[tid:%i] Blocking due to no free ROB/IQ/ entries.\n"
548 "ROB has %i free entries.\n"
549 "IQ has %i free entries.\n",
550 tid, free_rob_entries, free_iq_entries);
551
552 blockThisCycle = true;
553
554 block(tid);
555
556 incrFullStat(source);
557
558 return;
559 } else if (min_free_entries < insts_available) {
560 DPRINTF(Rename,
561 "[tid:%i] "
562 "Will have to block this cycle. "
563 "%i insts available, "
564 "but only %i insts can be renamed due to ROB/IQ/LSQ limits.\n",
565 tid, insts_available, min_free_entries);
566
567 insts_available = min_free_entries;
568
569 blockThisCycle = true;
570
571 incrFullStat(source);
572 }
573
574 InstQueue &insts_to_rename = renameStatus[tid] == Unblocking ?
575 skidBuffer[tid] : insts[tid];
576
577 DPRINTF(Rename,
578 "[tid:%i] "
579 "%i available instructions to send iew.\n",
580 tid, insts_available);
581
582 DPRINTF(Rename,
583 "[tid:%i] "
584 "%i insts pipelining from Rename | "
585 "%i insts dispatched to IQ last cycle.\n",
586 tid, instsInProgress[tid], fromIEW->iewInfo[tid].dispatched);
587
588 // Handle serializing the next instruction if necessary.
589 if (serializeOnNextInst[tid]) {
590 if (emptyROB[tid] && instsInProgress[tid] == 0) {
591 // ROB already empty; no need to serialize.
592 serializeOnNextInst[tid] = false;
593 } else if (!insts_to_rename.empty()) {
594 insts_to_rename.front()->setSerializeBefore();
595 }
596 }
597
598 int renamed_insts = 0;
599
600 while (insts_available > 0 && toIEWIndex < renameWidth) {
601 DPRINTF(Rename, "[tid:%i] Sending instructions to IEW.\n", tid);
602
603 assert(!insts_to_rename.empty());
604
605 DynInstPtr inst = insts_to_rename.front();
606
607 //For all kind of instructions, check ROB and IQ first
608 //For load instruction, check LQ size and take into account the inflight loads
609 //For store instruction, check SQ size and take into account the inflight stores
610
611 if (inst->isLoad()) {
612 if (calcFreeLQEntries(tid) <= 0) {
613 DPRINTF(Rename, "[tid:%i] Cannot rename due to no free LQ\n",
614 tid);
615 source = LQ;
616 incrFullStat(source);
617 break;
618 }
619 }
620
621 if (inst->isStore() || inst->isAtomic()) {
622 if (calcFreeSQEntries(tid) <= 0) {
623 DPRINTF(Rename, "[tid:%i] Cannot rename due to no free SQ\n",
624 tid);
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 std::list<ThreadID>::iterator threads = activeThreads->begin();
819 std::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 std::list<ThreadID>::iterator threads = activeThreads->begin();
838 std::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__