45 #ifndef __CPU_O3_RENAME_IMPL_HH__
46 #define __CPU_O3_RENAME_IMPL_HH__
50 #include "arch/isa_traits.hh"
51 #include "arch/registers.hh"
52 #include "config/the_isa.hh"
55 #include "debug/Activity.hh"
56 #include "debug/Rename.hh"
57 #include "debug/O3PipeView.hh"
58 #include "params/DerivO3CPU.hh"
65 iewToRenameDelay(params->iewToRenameDelay),
66 decodeToRenameDelay(params->decodeToRenameDelay),
67 commitToRenameDelay(params->commitToRenameDelay),
68 renameWidth(params->renameWidth),
69 commitWidth(params->commitWidth),
70 numThreads(params->numThreads),
71 maxPhysicalRegs(params->numPhysIntRegs + params->numPhysFloatRegs
72 + params->numPhysCCRegs)
75 fatal(
"renameWidth (%d) is larger than compiled limit (%d),\n"
76 "\tincrease MaxWidth in src/cpu/o3/impl.hh\n",
87 return cpu->name() +
".rename";
95 .name(
name() +
".SquashCycles")
96 .desc(
"Number of cycles rename is squashing")
97 .prereq(renameSquashCycles);
99 .name(
name() +
".IdleCycles")
100 .desc(
"Number of cycles rename is idle")
101 .prereq(renameIdleCycles);
103 .name(
name() +
".BlockCycles")
104 .desc(
"Number of cycles rename is blocking")
105 .prereq(renameBlockCycles);
106 renameSerializeStallCycles
107 .name(
name() +
".serializeStallCycles")
108 .desc(
"count of cycles rename stalled for serializing inst")
111 .name(
name() +
".RunCycles")
112 .desc(
"Number of cycles rename is running")
113 .prereq(renameIdleCycles);
115 .name(
name() +
".UnblockCycles")
116 .desc(
"Number of cycles rename is unblocking")
117 .prereq(renameUnblockCycles);
119 .name(
name() +
".RenamedInsts")
120 .desc(
"Number of instructions processed by rename")
121 .prereq(renameRenamedInsts);
123 .name(
name() +
".SquashedInsts")
124 .desc(
"Number of squashed instructions processed by rename")
125 .prereq(renameSquashedInsts);
127 .name(
name() +
".ROBFullEvents")
128 .desc(
"Number of times rename has blocked due to ROB full")
129 .prereq(renameROBFullEvents);
131 .name(
name() +
".IQFullEvents")
132 .desc(
"Number of times rename has blocked due to IQ full")
133 .prereq(renameIQFullEvents);
135 .name(
name() +
".LQFullEvents")
136 .desc(
"Number of times rename has blocked due to LQ full")
137 .prereq(renameLQFullEvents);
139 .name(
name() +
".SQFullEvents")
140 .desc(
"Number of times rename has blocked due to SQ full")
141 .prereq(renameSQFullEvents);
142 renameFullRegistersEvents
143 .name(
name() +
".FullRegisterEvents")
144 .desc(
"Number of times there has been no free registers")
145 .prereq(renameFullRegistersEvents);
146 renameRenamedOperands
147 .name(
name() +
".RenamedOperands")
148 .desc(
"Number of destination operands rename has renamed")
149 .prereq(renameRenamedOperands);
151 .name(
name() +
".RenameLookups")
152 .desc(
"Number of register rename lookups that rename has made")
153 .prereq(renameRenameLookups);
155 .name(
name() +
".CommittedMaps")
156 .desc(
"Number of HB maps that are committed")
157 .prereq(renameCommittedMaps);
159 .name(
name() +
".UndoneMaps")
160 .desc(
"Number of HB maps that are undone due to squashing")
161 .prereq(renameUndoneMaps);
163 .name(
name() +
".serializingInsts")
164 .desc(
"count of serializing insts renamed")
167 renamedTempSerializing
168 .name(
name() +
".tempSerializingInsts")
169 .desc(
"count of temporary serializing insts renamed")
173 .name(
name() +
".skidInsts")
174 .desc(
"count of insts added to the skid buffer")
178 .name(
name() +
".int_rename_lookups")
179 .desc(
"Number of integer rename lookups")
180 .prereq(intRenameLookups);
182 .name(
name() +
".fp_rename_lookups")
183 .desc(
"Number of floating rename lookups")
184 .prereq(fpRenameLookups);
187 template <
class Impl>
196 template <
class Impl>
203 fromIEW = timeBuffer->
getWire(-iewToRenameDelay);
206 fromCommit = timeBuffer->getWire(-commitToRenameDelay);
209 toDecode = timeBuffer->getWire(0);
212 template <
class Impl>
216 renameQueue = rq_ptr;
219 toIEW = renameQueue->
getWire(0);
222 template <
class Impl>
226 decodeQueue = dq_ptr;
229 fromDecode = decodeQueue->
getWire(-decodeToRenameDelay);
232 template <
class Impl>
239 template <
class Impl>
245 resumeSerialize =
false;
246 resumeUnblocking =
false;
249 for (
ThreadID tid = 0; tid < numThreads; tid++) {
250 renameStatus[tid] = Idle;
252 freeEntries[tid].iqEntries = iew_ptr->instQueue.numFreeEntries(tid);
253 freeEntries[tid].lqEntries = iew_ptr->ldstQueue.numFreeLoadEntries(tid);
254 freeEntries[tid].sqEntries = iew_ptr->ldstQueue.numFreeStoreEntries(tid);
255 freeEntries[tid].robEntries = commit_ptr->numROBFreeEntries(tid);
256 emptyROB[tid] =
true;
258 stalls[tid].iew =
false;
259 serializeInst[tid] = NULL;
261 instsInProgress[tid] = 0;
262 loadsInProgress[tid] = 0;
263 storesInProgress[tid] = 0;
265 serializeOnNextInst[tid] =
false;
273 activeThreads = at_ptr;
277 template <
class Impl>
281 for (
ThreadID tid = 0; tid < numThreads; tid++)
282 renameMap[tid] = &rm_ptr[tid];
285 template <
class Impl>
296 scoreboard = _scoreboard;
299 template <
class Impl>
303 for (
ThreadID tid = 0; tid < numThreads; tid++) {
304 if (instsInProgress[tid] != 0 ||
305 !historyBuffer[tid].empty() ||
306 !skidBuffer[tid].empty() ||
307 !insts[tid].empty() ||
308 (renameStatus[tid] != Idle && renameStatus[tid] !=
Running))
314 template <
class Impl>
321 template <
class Impl>
325 for (
ThreadID tid = 0; tid < numThreads; tid++) {
326 assert(historyBuffer[tid].empty());
327 assert(insts[tid].empty());
328 assert(skidBuffer[tid].empty());
329 assert(instsInProgress[tid] == 0);
333 template <
class Impl>
337 DPRINTF(Rename,
"[tid:%u]: Squashing instructions.\n",tid);
342 if (renameStatus[tid] == Blocked ||
343 renameStatus[tid] == Unblocking) {
344 toDecode->renameUnblock[tid] = 1;
346 resumeSerialize =
false;
347 serializeInst[tid] = NULL;
348 }
else if (renameStatus[tid] == SerializeStall) {
349 if (serializeInst[tid]->seqNum <= squash_seq_num) {
350 DPRINTF(Rename,
"Rename will resume serializing after squash\n");
351 resumeSerialize =
true;
352 assert(serializeInst[tid]);
354 resumeSerialize =
false;
355 toDecode->renameUnblock[tid] = 1;
357 serializeInst[tid] = NULL;
362 renameStatus[tid] = Squashing;
365 for (
int i=0;
i<fromDecode->size;
i++) {
366 if (fromDecode->insts[
i]->threadNumber == tid &&
367 fromDecode->insts[
i]->seqNum > squash_seq_num) {
368 fromDecode->insts[
i]->setSquashed();
369 wroteToTimeBuffer =
true;
379 skidBuffer[tid].clear();
381 doSquash(squash_seq_num, tid);
384 template <
class Impl>
388 wroteToTimeBuffer =
false;
390 blockThisCycle =
false;
392 bool status_change =
false;
402 while (threads != end) {
405 DPRINTF(Rename,
"Processing [tid:%i]\n", tid);
407 status_change = checkSignalsAndUpdate(tid) || status_change;
409 rename(status_change, tid);
416 if (wroteToTimeBuffer) {
417 DPRINTF(Activity,
"Activity this cycle.\n");
418 cpu->activityThisCycle();
421 threads = activeThreads->begin();
423 while (threads != end) {
427 if (fromCommit->commitInfo[tid].doneSeqNum != 0 &&
428 !fromCommit->commitInfo[tid].squash &&
429 renameStatus[tid] != Squashing) {
431 removeFromHistory(fromCommit->commitInfo[tid].doneSeqNum,
437 for (
ThreadID tid = 0; tid < numThreads; tid++) {
438 instsInProgress[tid] -= fromIEW->iewInfo[tid].dispatched;
439 loadsInProgress[tid] -= fromIEW->iewInfo[tid].dispatchedToLQ;
440 storesInProgress[tid] -= fromIEW->iewInfo[tid].dispatchedToSQ;
441 assert(loadsInProgress[tid] >= 0);
442 assert(storesInProgress[tid] >= 0);
443 assert(instsInProgress[tid] >=0);
459 if (renameStatus[tid] == Blocked) {
461 }
else if (renameStatus[tid] == Squashing) {
462 ++renameSquashCycles;
463 }
else if (renameStatus[tid] == SerializeStall) {
464 ++renameSerializeStallCycles;
468 if (resumeSerialize) {
469 resumeSerialize =
false;
471 toDecode->renameUnblock[tid] =
false;
473 }
else if (renameStatus[tid] == Unblocking) {
474 if (resumeUnblocking) {
476 resumeUnblocking =
false;
477 toDecode->renameUnblock[tid] =
false;
481 if (renameStatus[tid] ==
Running ||
482 renameStatus[tid] == Idle) {
483 DPRINTF(Rename,
"[tid:%u]: Not blocked, so attempting to run "
487 }
else if (renameStatus[tid] == Unblocking) {
498 status_change = unblock(tid) || status_change || blockThisCycle;
502 template <
class Impl>
508 int insts_available = renameStatus[tid] == Unblocking ?
509 skidBuffer[tid].size() : insts[tid].size();
513 if (insts_available == 0) {
514 DPRINTF(Rename,
"[tid:%u]: Nothing to do, breaking out early.\n",
519 }
else if (renameStatus[tid] == Unblocking) {
520 ++renameUnblockCycles;
521 }
else if (renameStatus[tid] ==
Running) {
529 int free_rob_entries = calcFreeROBEntries(tid);
530 int free_iq_entries = calcFreeIQEntries(tid);
531 int min_free_entries = free_rob_entries;
535 if (free_iq_entries < min_free_entries) {
536 min_free_entries = free_iq_entries;
541 if (min_free_entries <= 0) {
542 DPRINTF(Rename,
"[tid:%u]: Blocking due to no free ROB/IQ/ "
544 "ROB has %i free entries.\n"
545 "IQ has %i free entries.\n",
550 blockThisCycle =
true;
554 incrFullStat(source);
557 }
else if (min_free_entries < insts_available) {
558 DPRINTF(Rename,
"[tid:%u]: Will have to block this cycle."
559 "%i insts available, but only %i insts can be "
560 "renamed due to ROB/IQ/LSQ limits.\n",
561 tid, insts_available, min_free_entries);
563 insts_available = min_free_entries;
565 blockThisCycle =
true;
567 incrFullStat(source);
570 InstQueue &insts_to_rename = renameStatus[tid] == Unblocking ?
571 skidBuffer[tid] : insts[tid];
573 DPRINTF(Rename,
"[tid:%u]: %i available instructions to "
574 "send iew.\n", tid, insts_available);
576 DPRINTF(Rename,
"[tid:%u]: %i insts pipelining from Rename | %i insts "
577 "dispatched to IQ last cycle.\n",
578 tid, instsInProgress[tid], fromIEW->iewInfo[tid].dispatched);
581 if (serializeOnNextInst[tid]) {
582 if (emptyROB[tid] && instsInProgress[tid] == 0) {
584 serializeOnNextInst[tid] =
false;
585 }
else if (!insts_to_rename.empty()) {
586 insts_to_rename.front()->setSerializeBefore();
590 int renamed_insts = 0;
592 while (insts_available > 0 && toIEWIndex < renameWidth) {
593 DPRINTF(Rename,
"[tid:%u]: Sending instructions to IEW.\n", tid);
595 assert(!insts_to_rename.empty());
597 inst = insts_to_rename.front();
603 if (inst->isLoad()) {
604 if (calcFreeLQEntries(tid) <= 0) {
605 DPRINTF(Rename,
"[tid:%u]: Cannot rename due to no free LQ\n");
607 incrFullStat(source);
612 if (inst->isStore()) {
613 if (calcFreeSQEntries(tid) <= 0) {
614 DPRINTF(Rename,
"[tid:%u]: Cannot rename due to no free SQ\n");
616 incrFullStat(source);
621 insts_to_rename.pop_front();
623 if (renameStatus[tid] == Unblocking) {
624 DPRINTF(Rename,
"[tid:%u]: Removing [sn:%lli] PC:%s from rename "
625 "skidBuffer\n", tid, inst->seqNum, inst->pcState());
628 if (inst->isSquashed()) {
629 DPRINTF(Rename,
"[tid:%u]: instruction %i with PC %s is "
630 "squashed, skipping.\n", tid, inst->seqNum,
633 ++renameSquashedInsts;
641 DPRINTF(Rename,
"[tid:%u]: Processing instruction [sn:%lli] with "
642 "PC %s.\n", tid, inst->seqNum, inst->pcState());
646 if (!renameMap[tid]->canRename(inst->numIntDestRegs(),
647 inst->numFPDestRegs(),
648 inst->numCCDestRegs())) {
649 DPRINTF(Rename,
"Blocking due to lack of free "
650 "physical registers to rename to.\n");
651 blockThisCycle =
true;
652 insts_to_rename.push_front(inst);
653 ++renameFullRegistersEvents;
668 if ((inst->isIprAccess() || inst->isSerializeBefore()) &&
669 !inst->isSerializeHandled()) {
670 DPRINTF(Rename,
"Serialize before instruction encountered.\n");
672 if (!inst->isTempSerializeBefore()) {
673 renamedSerializing++;
674 inst->setSerializeHandled();
676 renamedTempSerializing++;
681 renameStatus[tid] = SerializeStall;
683 serializeInst[tid] = inst;
685 blockThisCycle =
true;
688 }
else if ((inst->isStoreConditional() || inst->isSerializeAfter()) &&
689 !inst->isSerializeHandled()) {
690 DPRINTF(Rename,
"Serialize after instruction encountered.\n");
692 renamedSerializing++;
694 inst->setSerializeHandled();
696 serializeAfter(insts_to_rename, tid);
699 renameSrcRegs(inst, inst->threadNumber);
701 renameDestRegs(inst, inst->threadNumber);
703 if (inst->isLoad()) {
704 loadsInProgress[tid]++;
706 if (inst->isStore()) {
707 storesInProgress[tid]++;
712 ppRename->notify(inst);
715 toIEW->insts[toIEWIndex] = inst;
725 instsInProgress[tid] += renamed_insts;
726 renameRenamedInsts += renamed_insts;
730 wroteToTimeBuffer =
true;
735 if (insts_available) {
736 blockThisCycle =
true;
739 if (blockThisCycle) {
741 toDecode->renameUnblock[tid] =
false;
751 while (!insts[tid].empty()) {
752 inst = insts[tid].front();
754 insts[tid].pop_front();
756 assert(tid == inst->threadNumber);
758 DPRINTF(Rename,
"[tid:%u]: Inserting [sn:%lli] PC: %s into Rename "
759 "skidBuffer\n", tid, inst->seqNum, inst->pcState());
763 skidBuffer[tid].push_back(inst);
766 if (skidBuffer[tid].
size() > skidBufferMax)
768 typename InstQueue::iterator it;
769 warn(
"Skidbuffer contents:\n");
770 for (it = skidBuffer[tid].begin(); it != skidBuffer[tid].end(); it++)
772 warn(
"[tid:%u]: %s [sn:%i].\n", tid,
773 (*it)->staticInst->disassemble(inst->instAddr()),
776 panic(
"Skidbuffer Exceeded Max Size");
780 template <
class Impl>
784 int insts_from_decode = fromDecode->size;
785 for (
int i = 0;
i < insts_from_decode; ++
i) {
787 insts[inst->threadNumber].push_back(inst);
790 inst->renameTick =
curTick() - inst->fetchTick;
803 while (threads != end) {
806 if (!skidBuffer[tid].empty())
817 bool any_unblocking =
false;
822 while (threads != end) {
825 if (renameStatus[tid] == Unblocking) {
826 any_unblocking =
true;
832 if (any_unblocking) {
833 if (_status == Inactive) {
836 DPRINTF(Activity,
"Activating stage.\n");
838 cpu->activateStage(O3CPU::RenameIdx);
843 if (_status == Active) {
845 DPRINTF(Activity,
"Deactivating stage.\n");
847 cpu->deactivateStage(O3CPU::RenameIdx);
852 template <
class Impl>
856 DPRINTF(Rename,
"[tid:%u]: Blocking.\n", tid);
864 if (renameStatus[tid] != Blocked) {
868 if (resumeUnblocking || renameStatus[tid] != Unblocking) {
869 toDecode->renameBlock[tid] =
true;
870 toDecode->renameUnblock[tid] =
false;
871 wroteToTimeBuffer =
true;
876 if (renameStatus[tid] != SerializeStall) {
878 renameStatus[tid] = Blocked;
886 template <
class Impl>
890 DPRINTF(Rename,
"[tid:%u]: Trying to unblock.\n", tid);
893 if (skidBuffer[tid].empty() && renameStatus[tid] != SerializeStall) {
895 DPRINTF(Rename,
"[tid:%u]: Done unblocking.\n", tid);
897 toDecode->renameUnblock[tid] =
true;
898 wroteToTimeBuffer =
true;
907 template <
class Impl>
912 historyBuffer[tid].begin();
916 if (historyBuffer[tid].empty()) {
922 while (!historyBuffer[tid].empty() &&
923 hb_it->instSeqNum > squashed_seq_num) {
924 assert(hb_it != historyBuffer[tid].end());
926 DPRINTF(Rename,
"[tid:%u]: Removing history entry with sequence "
927 "number %i.\n", tid, hb_it->instSeqNum);
935 if (hb_it->newPhysReg != hb_it->prevPhysReg) {
938 renameMap[tid]->setEntry(hb_it->archReg, hb_it->prevPhysReg);
941 freeList->addReg(hb_it->newPhysReg);
947 ppSquashInRename->notify(std::make_pair(hb_it->instSeqNum,
950 historyBuffer[tid].erase(hb_it++);
960 DPRINTF(Rename,
"[tid:%u]: Removing a committed instruction from the "
961 "history buffer %u (size=%i), until [sn:%lli].\n",
962 tid, tid, historyBuffer[tid].
size(), inst_seq_num);
965 historyBuffer[tid].end();
969 if (historyBuffer[tid].empty()) {
970 DPRINTF(Rename,
"[tid:%u]: History buffer is empty.\n", tid);
972 }
else if (hb_it->instSeqNum > inst_seq_num) {
973 DPRINTF(Rename,
"[tid:%u]: Old sequence number encountered. Ensure "
974 "that a syscall happened recently.\n", tid);
982 while (!historyBuffer[tid].empty() &&
983 hb_it != historyBuffer[tid].end() &&
984 hb_it->instSeqNum <= inst_seq_num) {
986 DPRINTF(Rename,
"[tid:%u]: Freeing up older rename of reg %i, "
988 tid, hb_it->prevPhysReg, hb_it->instSeqNum);
993 if (hb_it->newPhysReg != hb_it->prevPhysReg) {
994 freeList->addReg(hb_it->prevPhysReg);
997 ++renameCommittedMaps;
999 historyBuffer[tid].erase(hb_it--);
1003 template <
class Impl>
1009 unsigned num_src_regs = inst->numSrcRegs();
1013 for (
int src_idx = 0; src_idx < num_src_regs; src_idx++) {
1014 RegIndex src_reg = inst->srcRegIdx(src_idx);
1022 renamed_reg = map->lookupInt(flat_rel_src_reg);
1028 renamed_reg = map->lookupFloat(flat_rel_src_reg);
1034 renamed_reg = map->lookupCC(flat_rel_src_reg);
1039 flat_rel_src_reg = rel_src_reg;
1040 renamed_reg = map->lookupMisc(flat_rel_src_reg);
1044 panic(
"Reg index is out of bound: %d.", src_reg);
1047 DPRINTF(Rename,
"[tid:%u]: Looking up %s arch reg %i (flattened %i), "
1049 (
int)src_reg, (
int)flat_rel_src_reg, (
int)renamed_reg);
1051 inst->renameSrcReg(src_idx, renamed_reg);
1054 if (scoreboard->getReg(renamed_reg)) {
1055 DPRINTF(Rename,
"[tid:%u]: Register %d is ready.\n",
1058 inst->markSrcRegReady(src_idx);
1060 DPRINTF(Rename,
"[tid:%u]: Register %d is not ready.\n",
1064 ++renameRenameLookups;
1068 template <
class Impl>
1074 unsigned num_dest_regs = inst->numDestRegs();
1077 for (
int dest_idx = 0; dest_idx < num_dest_regs; dest_idx++) {
1078 RegIndex dest_reg = inst->destRegIdx(dest_idx);
1082 typename RenameMap::RenameInfo rename_result;
1087 rename_result = map->renameInt(flat_rel_dest_reg);
1088 flat_uni_dest_reg = flat_rel_dest_reg;
1093 rename_result = map->renameFloat(flat_rel_dest_reg);
1099 rename_result = map->renameCC(flat_rel_dest_reg);
1105 flat_rel_dest_reg = rel_dest_reg;
1106 rename_result = map->renameMisc(flat_rel_dest_reg);
1111 panic(
"Reg index is out of bound: %d.", dest_reg);
1114 inst->flattenDestReg(dest_idx, flat_uni_dest_reg);
1117 scoreboard->unsetReg(rename_result.first);
1119 DPRINTF(Rename,
"[tid:%u]: Renaming arch reg %i to physical "
1120 "reg %i.\n", tid, (
int)flat_rel_dest_reg,
1121 (
int)rename_result.first);
1125 rename_result.first,
1126 rename_result.second);
1128 historyBuffer[tid].push_front(hb_entry);
1130 DPRINTF(Rename,
"[tid:%u]: Adding instruction to history buffer "
1131 "(size=%i), [sn:%lli].\n",tid,
1132 historyBuffer[tid].
size(),
1133 (*historyBuffer[tid].begin()).instSeqNum);
1140 inst->renameDestReg(dest_idx,
1141 rename_result.first,
1142 rename_result.second);
1144 ++renameRenamedOperands;
1148 template <
class Impl>
1152 int num_free = freeEntries[tid].robEntries -
1153 (instsInProgress[tid] - fromIEW->iewInfo[tid].dispatched);
1160 template <
class Impl>
1164 int num_free = freeEntries[tid].iqEntries -
1165 (instsInProgress[tid] - fromIEW->iewInfo[tid].dispatched);
1172 template <
class Impl>
1176 int num_free = freeEntries[tid].lqEntries -
1177 (loadsInProgress[tid] - fromIEW->iewInfo[tid].dispatchedToLQ);
1178 DPRINTF(Rename,
"calcFreeLQEntries: free lqEntries: %d, loadsInProgress: %d, "
1179 "loads dispatchedToLQ: %d\n", freeEntries[tid].lqEntries,
1180 loadsInProgress[tid], fromIEW->iewInfo[tid].dispatchedToLQ);
1184 template <
class Impl>
1188 int num_free = freeEntries[tid].sqEntries -
1189 (storesInProgress[tid] - fromIEW->iewInfo[tid].dispatchedToSQ);
1190 DPRINTF(Rename,
"calcFreeSQEntries: free sqEntries: %d, storesInProgress: %d, "
1191 "stores dispatchedToSQ: %d\n", freeEntries[tid].sqEntries,
1192 storesInProgress[tid], fromIEW->iewInfo[tid].dispatchedToSQ);
1196 template <
class Impl>
1200 unsigned inst_count = 0;
1202 for (
int i=0;
i<fromDecode->size;
i++) {
1203 if (!fromDecode->insts[
i]->isSquashed())
1210 template <
class Impl>
1214 if (fromIEW->iewBlock[tid]) {
1215 stalls[tid].iew =
true;
1218 if (fromIEW->iewUnblock[tid]) {
1219 assert(stalls[tid].iew);
1220 stalls[tid].iew =
false;
1224 template <
class Impl>
1228 bool ret_val =
false;
1230 if (stalls[tid].iew) {
1231 DPRINTF(Rename,
"[tid:%i]: Stall from IEW stage detected.\n", tid);
1233 }
else if (calcFreeROBEntries(tid) <= 0) {
1234 DPRINTF(Rename,
"[tid:%i]: Stall: ROB has 0 free entries.\n", tid);
1236 }
else if (calcFreeIQEntries(tid) <= 0) {
1237 DPRINTF(Rename,
"[tid:%i]: Stall: IQ has 0 free entries.\n", tid);
1239 }
else if (calcFreeLQEntries(tid) <= 0 && calcFreeSQEntries(tid) <= 0) {
1240 DPRINTF(Rename,
"[tid:%i]: Stall: LSQ has 0 free entries.\n", tid);
1242 }
else if (renameMap[tid]->numFreeEntries() <= 0) {
1243 DPRINTF(Rename,
"[tid:%i]: Stall: RenameMap has 0 free entries.\n", tid);
1245 }
else if (renameStatus[tid] == SerializeStall &&
1246 (!emptyROB[tid] || instsInProgress[tid])) {
1247 DPRINTF(Rename,
"[tid:%i]: Stall: Serialize stall and ROB is not "
1256 template <
class Impl>
1260 if (fromIEW->iewInfo[tid].usedIQ)
1261 freeEntries[tid].iqEntries = fromIEW->iewInfo[tid].freeIQEntries;
1263 if (fromIEW->iewInfo[tid].usedLSQ) {
1264 freeEntries[tid].lqEntries = fromIEW->iewInfo[tid].freeLQEntries;
1265 freeEntries[tid].sqEntries = fromIEW->iewInfo[tid].freeSQEntries;
1268 if (fromCommit->commitInfo[tid].usedROB) {
1269 freeEntries[tid].robEntries =
1270 fromCommit->commitInfo[tid].freeROBEntries;
1271 emptyROB[tid] = fromCommit->commitInfo[tid].emptyROB;
1274 DPRINTF(Rename,
"[tid:%i]: Free IQ: %i, Free ROB: %i, "
1275 "Free LQ: %i, Free SQ: %i\n",
1277 freeEntries[tid].iqEntries,
1278 freeEntries[tid].robEntries,
1279 freeEntries[tid].lqEntries,
1280 freeEntries[tid].sqEntries);
1282 DPRINTF(Rename,
"[tid:%i]: %i instructions not yet in ROB\n",
1283 tid, instsInProgress[tid]);
1286 template <
class Impl>
1300 readFreeEntries(tid);
1301 readStallSignals(tid);
1303 if (fromCommit->commitInfo[tid].squash) {
1304 DPRINTF(Rename,
"[tid:%u]: Squashing instructions due to squash from "
1307 squash(fromCommit->commitInfo[tid].doneSeqNum, tid);
1312 if (checkStall(tid)) {
1316 if (renameStatus[tid] == Blocked) {
1317 DPRINTF(Rename,
"[tid:%u]: Done blocking, switching to unblocking.\n",
1320 renameStatus[tid] = Unblocking;
1327 if (renameStatus[tid] == Squashing) {
1330 if (resumeSerialize) {
1331 DPRINTF(Rename,
"[tid:%u]: Done squashing, switching to serialize.\n",
1334 renameStatus[tid] = SerializeStall;
1336 }
else if (resumeUnblocking) {
1337 DPRINTF(Rename,
"[tid:%u]: Done squashing, switching to unblocking.\n",
1339 renameStatus[tid] = Unblocking;
1342 DPRINTF(Rename,
"[tid:%u]: Done squashing, switching to running.\n",
1350 if (renameStatus[tid] == SerializeStall) {
1352 DPRINTF(Rename,
"[tid:%u]: Done with serialize stall, switching to "
1353 "unblocking.\n", tid);
1357 renameStatus[tid] = Unblocking;
1361 DPRINTF(Rename,
"[tid:%u]: Processing instruction [%lli] with "
1362 "PC %s.\n", tid, serial_inst->seqNum, serial_inst->pcState());
1365 serial_inst->clearSerializeBefore();
1367 if (!skidBuffer[tid].empty()) {
1368 skidBuffer[tid].push_front(serial_inst);
1370 insts[tid].push_front(serial_inst);
1373 DPRINTF(Rename,
"[tid:%u]: Instruction must be processed by rename."
1374 " Adding to front of list.\n", tid);
1376 serializeInst[tid] = NULL;
1386 template<
class Impl>
1390 if (inst_list.empty()) {
1392 serializeOnNextInst[tid] =
true;
1397 inst_list.front()->setSerializeBefore();
1400 template <
class Impl>
1406 ++renameROBFullEvents;
1409 ++renameIQFullEvents;
1412 ++renameLQFullEvents;
1415 ++renameSQFullEvents;
1418 panic(
"Rename full stall stat should be incremented for a reason!");
1423 template <
class Impl>
1429 for (
ThreadID tid = 0; tid < numThreads; tid++) {
1431 buf_it = historyBuffer[tid].begin();
1433 while (buf_it != historyBuffer[tid].end()) {
1434 cprintf(
"Seq num: %i\nArch reg: %i New phys reg: %i Old phys "
1435 "reg: %i\n", (*buf_it).instSeqNum, (
int)(*buf_it).archReg,
1436 (
int)(*buf_it).newPhysReg, (
int)(*buf_it).prevPhysReg);
1443 #endif//__CPU_O3_RENAME_IMPL_HH__
void setScoreboard(Scoreboard *_scoreboard)
Sets pointer to the scoreboard.
int decodeToRenameDelay
Delay between decode and rename, in ticks.
void readStallSignals(ThreadID tid)
Reads signals telling rename to block/unblock.
bool unblock(ThreadID tid)
Switches rename to unblocking if the skid buffer is empty, and signals back that rename has unblocked...
Impl::DynInstPtr DynInstPtr
const std::string & name()
void setFreeList(FreeList *fl_ptr)
Sets pointer to the free list.
void setRenameQueue(TimeBuffer< RenameStruct > *rq_ptr)
Sets pointer to time buffer used to communicate to the next stage.
bool block(ThreadID tid)
Switches rename to blocking, and signals back that rename has become blocked.
bool isDrained() const
Has the stage drained?
void renameDestRegs(DynInstPtr &inst, ThreadID tid)
Renames the destination registers of an instruction.
void regProbePoints()
Registers probes.
void renameSrcRegs(DynInstPtr &inst, ThreadID tid)
Renames the source registers of an instruction.
int calcFreeSQEntries(ThreadID tid)
Calculates the number of free SQ entries for a specific thread.
void doSquash(const InstSeqNum &squash_seq_num, ThreadID tid)
Executes actual squash, removing squashed instructions.
CPUPol::FreeList FreeList
ThreadContext is the external interface to all thread state for anything outside of the CPU...
unsigned validInsts()
Returns the number of valid instructions coming from decode.
void dumpHistory()
Debugging function used to dump history buffer of renamings.
virtual int flattenFloatIndex(int reg)=0
bool checkSignalsAndUpdate(ThreadID tid)
Checks the signals and updates the status.
void regStats()
Registers statistics.
void renameInsts(ThreadID tid)
Renames instructions for the given thread.
Implements a simple scoreboard to track which registers are ready.
Tick curTick()
The current simulated tick.
bool skidsEmpty()
Returns if all of the skid buffers are empty.
void removeFromHistory(InstSeqNum inst_seq_num, ThreadID tid)
Removes a committed instruction's rename history.
void drainSanityCheck() const
Perform sanity checks after a drain.
CPUPol::RenameMap RenameMap
Holds the information for each destination register rename.
void readFreeEntries(ThreadID tid)
Gets the number of free entries for a specific thread.
void takeOverFrom()
Takes over from another CPU's thread.
void skidInsert(ThreadID tid)
Inserts unused instructions from a given thread into the skid buffer, to be renamed once rename unblo...
virtual int flattenIntIndex(int reg)=0
FullSource
Enum to record the source of a structure full stall.
int calcFreeROBEntries(ThreadID tid)
Calculates the number of free ROB entries for a specific thread.
void squash(const InstSeqNum &squash_seq_num, ThreadID tid)
Squashes all instructions in a thread.
virtual int flattenCCIndex(int reg)=0
const FlagsType total
Print the total.
void resetStage()
Reset this pipeline stage.
int16_t ThreadID
Thread index/ID type.
const char * RegClassStrings[]
Map enum values to strings for debugging.
void rename(bool &status_change, ThreadID tid)
Determines what to do based on rename's current status.
int calcFreeLQEntries(ThreadID tid)
Calculates the number of free LQ entries for a specific thread.
void setActiveThreads(std::list< ThreadID > *at_ptr)
Sets pointer to list of active threads.
void tick()
Ticks rename, which processes all input signals and attempts to rename as many instructions as possib...
TheISA::RegIndex RegIndex
std::string name() const
Returns the name of rename.
void startupStage()
Initializes variables for the stage.
void setTimeBuffer(TimeBuffer< TimeStruct > *tb_ptr)
Sets the main backwards communication time buffer pointer.
int calcFreeIQEntries(ThreadID tid)
Calculates the number of free IQ entries for a specific thread.
void sortInsts()
Separates instructions from decode into individual lists of instructions sorted by thread...
void setRenameMap(RenameMap rm_ptr[Impl::MaxThreads])
Sets pointer to rename maps (per-thread structures).
void incrFullStat(const FullSource &source)
Function used to increment the stat that corresponds to the source of the stall.
unsigned skidBufferMax
The maximum skid buffer size.
RegClass regIdxToClass(TheISA::RegIndex reg_idx, TheISA::RegIndex *rel_reg_idx=NULL)
Map a 'unified' architectural register index to its register class.
DefaultRename(O3CPU *_cpu, DerivO3CPUParams *params)
DefaultRename constructor.
void updateStatus()
Updates overall rename status based on all of the threads' statuses.
void serializeAfter(InstQueue &inst_list, ThreadID tid)
Either serializes on the next instruction available in the InstQueue, or records that it must seriali...
unsigned renameWidth
Rename width, in instructions.
bool checkStall(ThreadID tid)
Checks if any stages are telling rename to block.
void setDecodeQueue(TimeBuffer< DecodeStruct > *dq_ptr)
Sets pointer to time buffer coming from decode.
void cprintf(const char *format, const Args &...args)