44 #ifndef __CPU_O3_IEW_IMPL_IMPL_HH__
45 #define __CPU_O3_IEW_IMPL_IMPL_HH__
53 #include "arch/utility.hh"
54 #include "config/the_isa.hh"
59 #include "debug/Activity.hh"
60 #include "debug/Drain.hh"
61 #include "debug/IEW.hh"
62 #include "debug/O3PipeView.hh"
63 #include "params/DerivO3CPU.hh"
69 : issueToExecQueue(params->backComSize, params->forwardComSize),
71 instQueue(_cpu, this, params),
72 ldstQueue(_cpu, this, params),
73 fuPool(params->fuPool),
74 commitToIEWDelay(params->commitToIEWDelay),
75 renameToIEWDelay(params->renameToIEWDelay),
76 issueToExecuteDelay(params->issueToExecuteDelay),
77 dispatchWidth(params->dispatchWidth),
78 issueWidth(params->issueWidth),
79 wbWidth(params->wbWidth),
80 numThreads(params->numThreads)
83 fatal(
"dispatchWidth (%d) is larger than compiled limit (%d),\n"
84 "\tincrease MaxWidth in src/cpu/o3/impl.hh\n",
87 fatal(
"issueWidth (%d) is larger than compiled limit (%d),\n"
88 "\tincrease MaxWidth in src/cpu/o3/impl.hh\n",
91 fatal(
"wbWidth (%d) is larger than compiled limit (%d),\n"
92 "\tincrease MaxWidth in src/cpu/o3/impl.hh\n",
93 wbWidth, static_cast<int>(Impl::MaxWidth));
115 template <
class Impl>
119 return cpu->name() +
".iew";
122 template <
class Impl>
142 template <
class Impl>
146 using namespace Stats;
148 instQueue.regStats();
149 ldstQueue.regStats();
152 .name(
name() +
".iewIdleCycles")
153 .desc(
"Number of cycles IEW is idle");
156 .name(
name() +
".iewSquashCycles")
157 .desc(
"Number of cycles IEW is squashing");
160 .name(
name() +
".iewBlockCycles")
161 .desc(
"Number of cycles IEW is blocking");
164 .name(
name() +
".iewUnblockCycles")
165 .desc(
"Number of cycles IEW is unblocking");
168 .name(
name() +
".iewDispatchedInsts")
169 .desc(
"Number of instructions dispatched to IQ");
172 .name(
name() +
".iewDispSquashedInsts")
173 .desc(
"Number of squashed instructions skipped by dispatch");
176 .name(
name() +
".iewDispLoadInsts")
177 .desc(
"Number of dispatched load instructions");
180 .name(
name() +
".iewDispStoreInsts")
181 .desc(
"Number of dispatched store instructions");
184 .name(
name() +
".iewDispNonSpecInsts")
185 .desc(
"Number of dispatched non-speculative instructions");
188 .name(
name() +
".iewIQFullEvents")
189 .desc(
"Number of times the IQ has become full, causing a stall");
192 .name(
name() +
".iewLSQFullEvents")
193 .desc(
"Number of times the LSQ has become full, causing a stall");
195 memOrderViolationEvents
196 .name(
name() +
".memOrderViolationEvents")
197 .desc(
"Number of memory order violations");
199 predictedTakenIncorrect
200 .name(
name() +
".predictedTakenIncorrect")
201 .desc(
"Number of branches that were predicted taken incorrectly");
203 predictedNotTakenIncorrect
204 .name(
name() +
".predictedNotTakenIncorrect")
205 .desc(
"Number of branches that were predicted not taken incorrectly");
208 .name(
name() +
".branchMispredicts")
209 .desc(
"Number of branch mispredicts detected at execute");
211 branchMispredicts = predictedTakenIncorrect + predictedNotTakenIncorrect;
214 .name(
name() +
".iewExecutedInsts")
215 .desc(
"Number of executed instructions");
218 .init(cpu->numThreads)
219 .name(
name() +
".iewExecLoadInsts")
220 .desc(
"Number of load instructions executed")
224 .name(
name() +
".iewExecSquashedInsts")
225 .desc(
"Number of squashed instructions skipped in execute");
228 .init(cpu->numThreads)
229 .name(
name() +
".exec_swp")
230 .desc(
"number of swp insts executed")
234 .init(cpu->numThreads)
235 .name(
name() +
".exec_nop")
236 .desc(
"number of nop insts executed")
240 .init(cpu->numThreads)
241 .name(
name() +
".exec_refs")
242 .desc(
"number of memory reference insts executed")
246 .init(cpu->numThreads)
247 .name(
name() +
".exec_branches")
248 .desc(
"Number of branches executed")
252 .name(
name() +
".exec_stores")
253 .desc(
"Number of stores executed")
255 iewExecStoreInsts = iewExecutedRefs - iewExecLoadInsts;
258 .name(
name() +
".exec_rate")
259 .desc(
"Inst execution rate")
262 iewExecRate = iewExecutedInsts / cpu->numCycles;
265 .init(cpu->numThreads)
266 .name(
name() +
".wb_sent")
267 .desc(
"cumulative count of insts sent to commit")
271 .init(cpu->numThreads)
272 .name(
name() +
".wb_count")
273 .desc(
"cumulative count of insts written-back")
277 .init(cpu->numThreads)
278 .name(
name() +
".wb_producers")
279 .desc(
"num instructions producing a value")
283 .init(cpu->numThreads)
284 .name(
name() +
".wb_consumers")
285 .desc(
"num instructions consuming a value")
289 .name(
name() +
".wb_fanout")
290 .desc(
"average fanout of values written-back")
293 wbFanout = producerInst / consumerInst;
296 .name(
name() +
".wb_rate")
297 .desc(
"insts written-back per cycle")
299 wbRate = writebackCount / cpu->numCycles;
306 for (
ThreadID tid = 0; tid < numThreads; tid++) {
307 toRename->iewInfo[tid].usedIQ =
true;
308 toRename->iewInfo[tid].freeIQEntries =
309 instQueue.numFreeEntries(tid);
311 toRename->iewInfo[tid].usedLSQ =
true;
312 toRename->iewInfo[tid].freeLQEntries = ldstQueue.numFreeLoadEntries(tid);
313 toRename->iewInfo[tid].freeSQEntries = ldstQueue.numFreeStoreEntries(tid);
318 cpu->checker->setDcachePort(&cpu->getDataPort());
321 cpu->activateStage(O3CPU::IEWIdx);
331 fromCommit = timeBuffer->
getWire(-commitToIEWDelay);
334 toRename = timeBuffer->getWire(0);
336 toFetch = timeBuffer->getWire(0);
339 instQueue.setTimeBuffer(tb_ptr);
346 renameQueue = rq_ptr;
349 fromRename = renameQueue->
getWire(-renameToIEWDelay);
359 toCommit = iewQueue->
getWire(0);
366 activeThreads = at_ptr;
368 ldstQueue.setActiveThreads(at_ptr);
369 instQueue.setActiveThreads(at_ptr);
379 template <
class Impl>
383 bool drained = ldstQueue.isDrained() && instQueue.isDrained();
385 for (
ThreadID tid = 0; tid < numThreads; tid++) {
386 if (!insts[tid].empty()) {
387 DPRINTF(Drain,
"%i: Insts not empty.\n", tid);
390 if (!skidBuffer[tid].empty()) {
391 DPRINTF(Drain,
"%i: Skid buffer not empty.\n", tid);
394 drained = drained && dispatchStatus[tid] ==
Running;
400 if (drained && !fuPool->isDrained()) {
401 DPRINTF(Drain,
"FU pool still busy.\n");
408 template <
class Impl>
414 instQueue.drainSanityCheck();
415 ldstQueue.drainSanityCheck();
418 template <
class Impl>
427 instQueue.takeOverFrom();
428 ldstQueue.takeOverFrom();
429 fuPool->takeOverFrom();
432 cpu->activityThisCycle();
434 for (
ThreadID tid = 0; tid < numThreads; tid++) {
436 fetchRedirect[tid] =
false;
439 updateLSQNextCycle =
false;
441 for (
int i = 0;
i < issueToExecQueue.getSize(); ++
i) {
442 issueToExecQueue.advance();
450 DPRINTF(IEW,
"[tid:%i]: Squashing all instructions.\n", tid);
453 instQueue.squash(tid);
456 ldstQueue.squash(fromCommit->commitInfo[tid].doneSeqNum, tid);
457 updatedQueues =
true;
460 DPRINTF(IEW,
"[tid:%i]: Removing skidbuffer instructions until [sn:%i].\n",
461 tid, fromCommit->commitInfo[tid].doneSeqNum);
463 while (!skidBuffer[tid].empty()) {
464 if (skidBuffer[tid].front()->isLoad()) {
465 toRename->iewInfo[tid].dispatchedToLQ++;
467 if (skidBuffer[tid].front()->isStore()) {
468 toRename->iewInfo[tid].dispatchedToSQ++;
471 toRename->iewInfo[tid].dispatched++;
473 skidBuffer[tid].pop();
476 emptyRenameInsts(tid);
483 DPRINTF(IEW,
"[tid:%i]: Squashing from a specific instruction, PC: %s "
484 "[sn:%i].\n", tid, inst->pcState(), inst->seqNum);
486 if (!toCommit->squash[tid] ||
487 inst->seqNum < toCommit->squashedSeqNum[tid]) {
488 toCommit->squash[tid] =
true;
489 toCommit->squashedSeqNum[tid] = inst->seqNum;
490 toCommit->branchTaken[tid] = inst->pcState().branching();
495 toCommit->pc[tid] =
pc;
496 toCommit->mispredictInst[tid] = inst;
497 toCommit->includeSquashInst[tid] =
false;
499 wroteToTimeBuffer =
true;
508 DPRINTF(IEW,
"[tid:%i]: Memory violation, squashing violator and younger "
509 "insts, PC: %s [sn:%i].\n", tid, inst->pcState(), inst->seqNum);
516 if (!toCommit->squash[tid] ||
517 inst->seqNum <= toCommit->squashedSeqNum[tid]) {
518 toCommit->squash[tid] =
true;
520 toCommit->squashedSeqNum[tid] = inst->seqNum;
521 toCommit->pc[tid] = inst->pcState();
522 toCommit->mispredictInst[tid] = NULL;
525 toCommit->includeSquashInst[tid] =
true;
527 wroteToTimeBuffer =
true;
535 DPRINTF(IEW,
"[tid:%u]: Blocking.\n", tid);
537 if (dispatchStatus[tid] != Blocked &&
538 dispatchStatus[tid] != Unblocking) {
539 toRename->iewBlock[tid] =
true;
540 wroteToTimeBuffer =
true;
547 dispatchStatus[tid] = Blocked;
554 DPRINTF(IEW,
"[tid:%i]: Reading instructions out of the skid "
555 "buffer %u.\n",tid, tid);
559 if (skidBuffer[tid].empty()) {
560 toRename->iewUnblock[tid] =
true;
561 wroteToTimeBuffer =
true;
562 DPRINTF(IEW,
"[tid:%i]: Done unblocking.\n",tid);
571 instQueue.wakeDependents(inst);
578 instQueue.rescheduleMemInst(inst);
585 instQueue.replayMemInst(inst);
592 instQueue.blockMemInst(inst);
599 instQueue.cacheUnblocked();
616 while ((*iewQueue)[wbCycle].insts[wbNumInst]) {
618 if (wbNumInst == wbWidth) {
624 DPRINTF(IEW,
"Current wb cycle: %i, width: %i, numInst: %i\nwbActual:%i\n",
625 wbCycle, wbWidth, wbNumInst, wbCycle * wbWidth + wbNumInst);
627 (*iewQueue)[wbCycle].insts[wbNumInst] = inst;
628 (*iewQueue)[wbCycle].size++;
631 template <
class Impl>
635 unsigned inst_count = 0;
637 for (
int i=0;
i<fromRename->size;
i++) {
638 if (!fromRename->insts[
i]->isSquashed())
651 while (!insts[tid].empty()) {
652 inst = insts[tid].front();
656 DPRINTF(IEW,
"[tid:%i]: Inserting [sn:%lli] PC:%s into "
657 "dispatch skidBuffer %i\n",tid, inst->seqNum,
658 inst->pcState(),tid);
660 skidBuffer[tid].push(inst);
663 assert(skidBuffer[tid].
size() <= skidBufferMax &&
664 "Skidbuffer Exceeded Max Size");
676 while (threads != end) {
678 unsigned thread_count = skidBuffer[tid].size();
679 if (max < thread_count)
693 while (threads != end) {
696 if (!skidBuffer[tid].empty())
703 template <
class Impl>
707 bool any_unblocking =
false;
712 while (threads != end) {
715 if (dispatchStatus[tid] == Unblocking) {
716 any_unblocking =
true;
724 instQueue.intInstQueueReads++;
725 if (_status == Active && !instQueue.hasReadyInsts() &&
726 !ldstQueue.willWB() && !any_unblocking) {
727 DPRINTF(IEW,
"IEW switching to idle\n");
732 }
else if (_status == Inactive && (instQueue.hasReadyInsts() ||
733 ldstQueue.willWB() ||
736 DPRINTF(IEW,
"IEW switching to active\n");
744 template <
class Impl>
748 instQueue.resetEntries();
749 ldstQueue.resetEntries();
752 template <
class Impl>
758 if (fromCommit->commitInfo[tid].robSquashing) {
759 DPRINTF(IEW,
"[tid:%i]: Stall from Commit stage detected.\n",tid);
761 }
else if (instQueue.isFull(tid)) {
762 DPRINTF(IEW,
"[tid:%i]: Stall: IQ is full.\n",tid);
769 template <
class Impl>
780 if (fromCommit->commitInfo[tid].squash) {
783 if (dispatchStatus[tid] == Blocked ||
784 dispatchStatus[tid] == Unblocking) {
785 toRename->iewUnblock[tid] =
true;
786 wroteToTimeBuffer =
true;
789 dispatchStatus[tid] = Squashing;
790 fetchRedirect[tid] =
false;
794 if (fromCommit->commitInfo[tid].robSquashing) {
795 DPRINTF(IEW,
"[tid:%i]: ROB is still squashing.\n", tid);
797 dispatchStatus[tid] = Squashing;
798 emptyRenameInsts(tid);
799 wroteToTimeBuffer =
true;
802 if (checkStall(tid)) {
804 dispatchStatus[tid] = Blocked;
808 if (dispatchStatus[tid] == Blocked) {
811 DPRINTF(IEW,
"[tid:%i]: Done blocking, switching to unblocking.\n",
814 dispatchStatus[tid] = Unblocking;
821 if (dispatchStatus[tid] == Squashing) {
824 DPRINTF(IEW,
"[tid:%i]: Done squashing, switching to running.\n",
833 template <
class Impl>
837 int insts_from_rename = fromRename->size;
839 for (
ThreadID tid = 0; tid < numThreads; tid++)
840 assert(insts[tid].empty());
842 for (
int i = 0;
i < insts_from_rename; ++
i) {
843 insts[fromRename->insts[
i]->threadNumber].push(fromRename->insts[
i]);
847 template <
class Impl>
851 DPRINTF(IEW,
"[tid:%i]: Removing incoming rename instructions\n", tid);
853 while (!insts[tid].empty()) {
855 if (insts[tid].front()->isLoad()) {
856 toRename->iewInfo[tid].dispatchedToLQ++;
858 if (insts[tid].front()->isStore()) {
859 toRename->iewInfo[tid].dispatchedToSQ++;
862 toRename->iewInfo[tid].dispatched++;
868 template <
class Impl>
875 template <
class Impl>
879 DPRINTF(Activity,
"Activity this cycle.\n");
880 cpu->activityThisCycle();
883 template <
class Impl>
887 DPRINTF(Activity,
"Activating stage.\n");
888 cpu->activateStage(O3CPU::IEWIdx);
891 template <
class Impl>
895 DPRINTF(Activity,
"Deactivating stage.\n");
896 cpu->deactivateStage(O3CPU::IEWIdx);
910 if (dispatchStatus[tid] == Blocked) {
913 }
else if (dispatchStatus[tid] == Squashing) {
919 if (dispatchStatus[tid] ==
Running ||
920 dispatchStatus[tid] == Idle) {
921 DPRINTF(IEW,
"[tid:%i] Not blocked, so attempting to run "
925 }
else if (dispatchStatus[tid] == Unblocking) {
928 assert(!skidsEmpty());
937 if (validInstsFromRename()) {
947 template <
class Impl>
953 std::queue<DynInstPtr> &insts_to_dispatch =
954 dispatchStatus[tid] == Unblocking ?
955 skidBuffer[tid] : insts[tid];
957 int insts_to_add = insts_to_dispatch.size();
960 bool add_to_iq =
false;
961 int dis_num_inst = 0;
965 for ( ; dis_num_inst < insts_to_add &&
966 dis_num_inst < dispatchWidth;
969 inst = insts_to_dispatch.front();
971 if (dispatchStatus[tid] == Unblocking) {
972 DPRINTF(IEW,
"[tid:%i]: Issue: Examining instruction from skid "
979 DPRINTF(IEW,
"[tid:%i]: Issue: Adding PC %s [sn:%lli] [tid:%i] to "
981 tid, inst->pcState(), inst->seqNum, inst->threadNumber);
988 if (inst->isSquashed()) {
989 DPRINTF(IEW,
"[tid:%i]: Issue: Squashed instruction encountered, "
990 "not adding to IQ.\n", tid);
992 ++iewDispSquashedInsts;
994 insts_to_dispatch.pop();
997 if (inst->isLoad()) {
998 toRename->iewInfo[tid].dispatchedToLQ++;
1000 if (inst->isStore()) {
1001 toRename->iewInfo[tid].dispatchedToSQ++;
1004 toRename->iewInfo[tid].dispatched++;
1010 if (instQueue.isFull(tid)) {
1011 DPRINTF(IEW,
"[tid:%i]: Issue: IQ has become full.\n", tid);
1019 toRename->iewUnblock[tid] =
false;
1026 if ((inst->isLoad() && ldstQueue.lqFull(tid)) ||
1027 (inst->isStore() && ldstQueue.sqFull(tid))) {
1028 DPRINTF(IEW,
"[tid:%i]: Issue: %s has become full.\n",tid,
1029 inst->isLoad() ?
"LQ" :
"SQ");
1037 toRename->iewUnblock[tid] =
false;
1044 if (inst->isLoad()) {
1045 DPRINTF(IEW,
"[tid:%i]: Issue: Memory instruction "
1046 "encountered, adding to LSQ.\n", tid);
1050 ldstQueue.insertLoad(inst);
1056 toRename->iewInfo[tid].dispatchedToLQ++;
1057 }
else if (inst->isStore()) {
1058 DPRINTF(IEW,
"[tid:%i]: Issue: Memory instruction "
1059 "encountered, adding to LSQ.\n", tid);
1061 ldstQueue.insertStore(inst);
1063 ++iewDispStoreInsts;
1065 if (inst->isStoreConditional()) {
1070 inst->setCanCommit();
1071 instQueue.insertNonSpec(inst);
1074 ++iewDispNonSpecInsts;
1079 toRename->iewInfo[tid].dispatchedToSQ++;
1080 }
else if (inst->isMemBarrier() || inst->isWriteBarrier()) {
1082 inst->setCanCommit();
1083 instQueue.insertBarrier(inst);
1085 }
else if (inst->isNop()) {
1086 DPRINTF(IEW,
"[tid:%i]: Issue: Nop instruction encountered, "
1087 "skipping.\n", tid);
1090 inst->setExecuted();
1091 inst->setCanCommit();
1093 instQueue.recordProducer(inst);
1095 iewExecutedNop[tid]++;
1099 assert(!inst->isExecuted());
1103 if (inst->isNonSpeculative()) {
1104 DPRINTF(IEW,
"[tid:%i]: Issue: Nonspeculative instruction "
1105 "encountered, skipping.\n", tid);
1108 inst->setCanCommit();
1111 instQueue.insertNonSpec(inst);
1113 ++iewDispNonSpecInsts;
1121 instQueue.insert(inst);
1124 insts_to_dispatch.pop();
1126 toRename->iewInfo[tid].dispatched++;
1128 ++iewDispatchedInsts;
1131 inst->dispatchTick =
curTick() - inst->fetchTick;
1133 ppDispatch->notify(inst);
1136 if (!insts_to_dispatch.empty()) {
1137 DPRINTF(IEW,
"[tid:%i]: Issue: Bandwidth Full. Blocking.\n", tid);
1139 toRename->iewUnblock[tid] =
false;
1142 if (dispatchStatus[tid] == Idle && dis_num_inst) {
1143 dispatchStatus[tid] =
Running;
1145 updatedQueues =
true;
1151 template <
class Impl>
1157 std::cout <<
"Available Instructions: ";
1159 while (fromIssue->insts[inst]) {
1161 if (inst%3==0) std::cout <<
"\n\t";
1163 std::cout <<
"PC: " << fromIssue->insts[inst]->pcState()
1164 <<
" TN: " << fromIssue->insts[inst]->threadNumber
1165 <<
" SN: " << fromIssue->insts[inst]->seqNum <<
" | ";
1174 template <
class Impl>
1184 while (threads != end) {
1186 fetchRedirect[tid] =
false;
1194 int insts_to_execute = fromIssue->size;
1196 for (; inst_num < insts_to_execute;
1199 DPRINTF(IEW,
"Execute: Executing instructions from IQ.\n");
1201 DynInstPtr inst = instQueue.getInstToExecute();
1203 DPRINTF(IEW,
"Execute: Processing PC %s, [tid:%i] [sn:%i].\n",
1204 inst->pcState(), inst->threadNumber,inst->seqNum);
1208 ppExecute->notify(inst);
1211 if (inst->isSquashed()) {
1212 DPRINTF(IEW,
"Execute: Instruction was squashed. PC: %s, [tid:%i]"
1213 " [sn:%i]\n", inst->pcState(), inst->threadNumber,
1218 inst->setExecuted();
1222 inst->setCanCommit();
1224 ++iewExecSquashedInsts;
1234 if (inst->isMemRef()) {
1235 DPRINTF(IEW,
"Execute: Calculating address for memory "
1239 if (inst->isLoad()) {
1242 fault = ldstQueue.executeLoad(inst);
1244 if (inst->isTranslationDelayed() &&
1248 DPRINTF(IEW,
"Execute: Delayed translation, deferring "
1250 instQueue.deferMemInst(inst);
1254 if (inst->isDataPrefetch() || inst->isInstPrefetch()) {
1257 }
else if (inst->isStore()) {
1258 fault = ldstQueue.executeStore(inst);
1260 if (inst->isTranslationDelayed() &&
1264 DPRINTF(IEW,
"Execute: Delayed translation, deferring "
1266 instQueue.deferMemInst(inst);
1271 if (fault !=
NoFault || !inst->readPredicate() ||
1272 !inst->isStoreConditional()) {
1277 inst->setExecuted();
1279 activityThisCycle();
1286 panic(
"Unexpected memory type!\n");
1294 if (inst->getFault() ==
NoFault) {
1296 if (!inst->readPredicate())
1297 inst->forwardOldRegs();
1300 inst->setExecuted();
1305 updateExeInstStats(inst);
1317 if (!fetchRedirect[tid] ||
1318 !toCommit->squash[tid] ||
1319 toCommit->squashedSeqNum[tid] > inst->seqNum) {
1323 bool loadNotExecuted = !inst->isExecuted() && inst->isLoad();
1325 if (inst->mispredicted() && !loadNotExecuted) {
1326 fetchRedirect[tid] =
true;
1328 DPRINTF(IEW,
"Execute: Branch mispredict detected.\n");
1329 DPRINTF(IEW,
"Predicted target was PC: %s.\n",
1330 inst->readPredTarg());
1331 DPRINTF(IEW,
"Execute: Redirecting fetch to PC: %s.\n",
1334 squashDueToBranch(inst, tid);
1336 ppMispredict->notify(inst);
1338 if (inst->readPredTaken()) {
1339 predictedTakenIncorrect++;
1341 predictedNotTakenIncorrect++;
1343 }
else if (ldstQueue.violation(tid)) {
1344 assert(inst->isMemRef());
1349 violator = ldstQueue.getMemDepViolator(tid);
1351 DPRINTF(IEW,
"LDSTQ detected a violation. Violator PC: %s "
1352 "[sn:%lli], inst PC: %s [sn:%lli]. Addr is: %#x.\n",
1353 violator->pcState(), violator->seqNum,
1354 inst->pcState(), inst->seqNum, inst->physEffAddrLow);
1356 fetchRedirect[tid] =
true;
1359 instQueue.violation(inst, violator);
1362 squashDueToMemOrder(violator, tid);
1364 ++memOrderViolationEvents;
1369 if (ldstQueue.violation(tid)) {
1370 assert(inst->isMemRef());
1372 DynInstPtr violator = ldstQueue.getMemDepViolator(tid);
1374 DPRINTF(IEW,
"LDSTQ detected a violation. Violator PC: "
1375 "%s, inst PC: %s. Addr is: %#x.\n",
1376 violator->pcState(), inst->pcState(),
1377 inst->physEffAddrLow);
1378 DPRINTF(IEW,
"Violation will not be handled because "
1379 "already squashing\n");
1381 ++memOrderViolationEvents;
1388 if (exeStatus == Idle) {
1392 updatedQueues =
true;
1394 cpu->activityThisCycle();
1404 template <
class Impl>
1413 for (
int inst_num = 0; inst_num < wbWidth &&
1414 toCommit->insts[inst_num]; inst_num++) {
1418 DPRINTF(IEW,
"Sending instructions to commit, [sn:%lli] PC %s.\n",
1419 inst->seqNum, inst->pcState());
1421 iewInstsToCommit[tid]++;
1424 ppToCommit->notify(inst);
1431 if (!inst->isSquashed() && inst->isExecuted() && inst->getFault() ==
NoFault) {
1432 int dependents = instQueue.wakeDependents(inst);
1434 for (
int i = 0;
i < inst->numDestRegs();
i++) {
1436 DPRINTF(IEW,
"Setting Destination Register %i\n",
1437 inst->renamedDestRegIdx(
i));
1438 scoreboard->setReg(inst->renamedDestRegIdx(
i));
1442 producerInst[tid]++;
1443 consumerInst[tid]+= dependents;
1445 writebackCount[tid]++;
1450 template<
class Impl>
1457 wroteToTimeBuffer =
false;
1458 updatedQueues =
false;
1463 fuPool->processFreeUnits();
1469 while (threads != end) {
1472 DPRINTF(IEW,
"Issue: Processing [tid:%i]\n",tid);
1474 checkSignalsAndUpdate(tid);
1478 if (exeStatus != Squashing) {
1486 instQueue.scheduleReadyInsts();
1490 issueToExecQueue.advance();
1493 bool broadcast_free_entries =
false;
1495 if (updatedQueues || exeStatus ==
Running || updateLSQNextCycle) {
1497 updateLSQNextCycle =
false;
1499 broadcast_free_entries =
true;
1503 ldstQueue.writebackStores();
1510 threads = activeThreads->begin();
1511 while (threads != end) {
1514 DPRINTF(IEW,
"Processing [tid:%i]\n",tid);
1517 if (fromCommit->commitInfo[tid].doneSeqNum != 0 &&
1518 !fromCommit->commitInfo[tid].squash &&
1519 !fromCommit->commitInfo[tid].robSquashing) {
1521 ldstQueue.commitStores(fromCommit->commitInfo[tid].doneSeqNum,tid);
1523 ldstQueue.commitLoads(fromCommit->commitInfo[tid].doneSeqNum,tid);
1525 updateLSQNextCycle =
true;
1526 instQueue.commit(fromCommit->commitInfo[tid].doneSeqNum,tid);
1529 if (fromCommit->commitInfo[tid].nonSpecSeqNum != 0) {
1532 if (fromCommit->commitInfo[tid].strictlyOrdered) {
1533 instQueue.replayMemInst(
1534 fromCommit->commitInfo[tid].strictlyOrderedLoad);
1535 fromCommit->commitInfo[tid].strictlyOrderedLoad->setAtCommit();
1537 instQueue.scheduleNonSpec(
1538 fromCommit->commitInfo[tid].nonSpecSeqNum);
1542 if (broadcast_free_entries) {
1543 toFetch->iewInfo[tid].iqCount =
1544 instQueue.getCount(tid);
1545 toFetch->iewInfo[tid].ldstqCount =
1546 ldstQueue.getCount(tid);
1548 toRename->iewInfo[tid].usedIQ =
true;
1549 toRename->iewInfo[tid].freeIQEntries =
1550 instQueue.numFreeEntries(tid);
1551 toRename->iewInfo[tid].usedLSQ =
true;
1553 toRename->iewInfo[tid].freeLQEntries =
1554 ldstQueue.numFreeLoadEntries(tid);
1555 toRename->iewInfo[tid].freeSQEntries =
1556 ldstQueue.numFreeStoreEntries(tid);
1558 wroteToTimeBuffer =
true;
1561 DPRINTF(IEW,
"[tid:%i], Dispatch dispatched %i instructions.\n",
1562 tid, toRename->iewInfo[tid].dispatched);
1565 DPRINTF(IEW,
"IQ has %i free entries (Can schedule: %i). "
1566 "LQ has %i free entries. SQ has %i free entries.\n",
1567 instQueue.numFreeEntries(), instQueue.hasReadyInsts(),
1568 ldstQueue.numFreeLoadEntries(), ldstQueue.numFreeStoreEntries());
1572 if (wroteToTimeBuffer) {
1573 DPRINTF(Activity,
"Activity this cycle.\n");
1574 cpu->activityThisCycle();
1578 template <
class Impl>
1587 if (
DTRACE(O3PipeView)) {
1588 inst->completeTick =
curTick() - inst->fetchTick;
1595 if (inst->isControl())
1596 iewExecutedBranches[tid]++;
1601 if (inst->isMemRef()) {
1602 iewExecutedRefs[tid]++;
1604 if (inst->isLoad()) {
1605 iewExecLoadInsts[tid]++;
1610 template <
class Impl>
1616 if (!fetchRedirect[tid] ||
1617 !toCommit->squash[tid] ||
1618 toCommit->squashedSeqNum[tid] > inst->seqNum) {
1620 if (inst->mispredicted()) {
1621 fetchRedirect[tid] =
true;
1623 DPRINTF(IEW,
"Execute: Branch mispredict detected.\n");
1624 DPRINTF(IEW,
"Predicted target was PC:%#x, NPC:%#x.\n",
1625 inst->predInstAddr(), inst->predNextInstAddr());
1626 DPRINTF(IEW,
"Execute: Redirecting fetch to PC: %#x,"
1627 " NPC: %#x.\n", inst->nextInstAddr(),
1628 inst->nextInstAddr());
1630 squashDueToBranch(inst, tid);
1632 if (inst->readPredTaken()) {
1633 predictedTakenIncorrect++;
1635 predictedNotTakenIncorrect++;
1641 #endif//__CPU_O3_IEW_IMPL_IMPL_HH__
Cycles renameToIEWDelay
Rename to IEW delay.
void setTimeBuffer(TimeBuffer< TimeStruct > *tb_ptr)
Sets main time buffer used for backwards communication.
unsigned issueWidth
Width of issue, in instructions.
bool fetchRedirect[Impl::MaxThreads]
Records if there is a fetch redirect on this cycle for each thread.
StageStatus exeStatus
Execute status.
decltype(nullptr) constexpr NoFault
void setIEWQueue(TimeBuffer< IEWStruct > *iq_ptr)
Sets time buffer to pass on instructions to commit.
const std::string & name()
void setRenameQueue(TimeBuffer< RenameStruct > *rq_ptr)
Sets time buffer for getting instructions coming from rename.
void startupStage()
Initializes stage; sends back the number of free IQ and LSQ entries.
void unblock(ThreadID tid)
Unblocks Dispatch if the skid buffer is empty, and signals back to other stages to unblock...
void squashDueToMemOrder(DynInstPtr &inst, ThreadID tid)
Sends commit proper information for a squash due to a memory order violation.
void checkMisprediction(DynInstPtr &inst)
Check misprediction.
ThreadID numThreads
Number of active threads.
void printAvailableInsts()
Debug function to print instructions that are issued this cycle.
Cycles issueToExecuteDelay
Issue to execute delay.
DefaultIEW(O3CPU *_cpu, DerivO3CPUParams *params)
Constructs a DefaultIEW with the given parameters.
void blockMemInst(DynInstPtr &inst)
Moves memory instruction onto the list of cache blocked instructions.
void squash(ThreadID tid)
Squashes instructions in IEW for a specific thread.
bool checkStall(ThreadID tid)
Checks if any of the stall conditions are currently true.
unsigned dispatchWidth
Width of dispatch, in instructions.
StageStatus wbStatus
Writeback status.
unsigned validInstsFromRename()
Returns the number of valid, non-squashed instructions coming from rename to dispatch.
Implements a simple scoreboard to track which registers are ready.
void cacheUnblocked()
Notifies that the cache has become unblocked.
IQ instQueue
Instruction queue.
TimeBuffer< IssueStruct >::wire fromIssue
Wire to read information from the issue stage time queue.
Tick curTick()
The current simulated tick.
void activateStage()
Tells CPU that the IEW stage is active and running.
void instToCommit(DynInstPtr &inst)
Sends an instruction to commit through the time buffer.
void dispatchInsts(ThreadID tid)
Dispatches instructions to IQ and LSQ.
Status _status
Overall stage status.
TimeBuffer< IssueStruct > issueToExecQueue
Issue stage queue.
void takeOverFrom()
Takes over from another CPU's thread.
void tick()
Ticks IEW stage, causing Dispatch, the IQ, the LSQ, Execute, and Writeback to run for one cycle...
bool isDrained() const
Has the stage drained?
void emptyRenameInsts(ThreadID tid)
Removes instructions from rename from a thread's instruction list.
void checkSignalsAndUpdate(ThreadID tid)
Processes inputs and changes state accordingly.
unsigned wbWidth
Writeback width.
void wakeCPU()
Tells the CPU to wakeup if it has descheduled itself due to no activity.
void advancePC(PCState &pc, const StaticInstPtr &inst)
bool updateLSQNextCycle
Records if the LSQ needs to be updated on the next cycle, so that IEW knows if there will be activity...
const FlagsType total
Print the total.
void squashDueToBranch(DynInstPtr &inst, ThreadID tid)
Sends commit proper information for a squash due to a branch mispredict.
void activityThisCycle()
Reports to the CPU that there is activity this cycle.
int16_t ThreadID
Thread index/ID type.
void setActiveThreads(std::list< ThreadID > *at_ptr)
Sets pointer to list of active threads.
void regStats()
Registers statistics.
int skidCount()
Returns the max of the number of entries in all of the skid buffers.
void setScoreboard(Scoreboard *sb_ptr)
Sets pointer to the scoreboard.
void executeInsts()
Executes instructions.
void drainSanityCheck() const
Perform sanity checks after a drain.
GenericISA::SimplePCState< MachInst > PCState
void writebackInsts()
Writebacks instructions.
void sortInsts()
Sorts instructions coming from rename into lists separated by thread.
void dispatch(ThreadID tid)
Determines proper actions to take given Dispatch's status.
void skidInsert(ThreadID tid)
Inserts unused instructions of a thread into the skid buffer.
void rescheduleMemInst(DynInstPtr &inst)
Tells memory dependence unit that a memory instruction needs to be rescheduled.
void deactivateStage()
Tells CPU that the IEW stage is inactive and idle.
bool skidsEmpty()
Returns if all of the skid buffers are empty.
unsigned skidBufferMax
Maximum size of the skid buffer.
Impl::DynInstPtr DynInstPtr
void wakeDependents(DynInstPtr &inst)
Wakes all dependents of a completed instruction.
void resetEntries()
Resets entries of the IQ and the LSQ.
StageStatus dispatchStatus[Impl::MaxThreads]
Dispatch status.
void updateExeInstStats(DynInstPtr &inst)
Updates execution stats based on the instruction.
void block(ThreadID tid)
Sets Dispatch to blocked, and signals back to other stages to block.
std::shared_ptr< FaultBase > Fault
void regProbePoints()
Registers probes.
std::string name() const
Returns the name of the DefaultIEW stage.
void updateStatus()
Updates overall IEW status based on all of the stages' statuses.
void replayMemInst(DynInstPtr &inst)
Re-executes all rescheduled memory instructions.