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