44 #ifndef __CPU_O3_COMMIT_IMPL_HH__
45 #define __CPU_O3_COMMIT_IMPL_HH__
51 #include "arch/utility.hh"
54 #include "config/the_isa.hh"
61 #include "debug/Activity.hh"
62 #include "debug/Commit.hh"
63 #include "debug/CommitRate.hh"
64 #include "debug/Drain.hh"
65 #include "debug/ExecFaulting.hh"
66 #include "debug/O3PipeView.hh"
67 #include "params/DerivO3CPU.hh"
76 :
Event(CPU_Tick_Pri, AutoDelete), commit(_commit), tid(_tid)
86 commit->trapSquash[tid] =
true;
113 fatal(
"commitWidth (%d) is larger than compiled limit (%d),\n"
114 "\tincrease MaxWidth in src/cpu/o3/impl.hh\n",
119 std::string policy = params->smtCommitPolicy;
122 std::transform(policy.begin(), policy.end(), policy.begin(),
123 (int(*)(int)) tolower);
126 if (policy ==
"aggressive"){
129 DPRINTF(Commit,
"Commit Policy set to Aggressive.\n");
130 }
else if (policy ==
"roundrobin"){
138 DPRINTF(Commit,
"Commit Policy set to Round Robin.\n");
139 }
else if (policy ==
"oldestready"){
142 DPRINTF(Commit,
"Commit Policy set to Oldest Ready.");
144 assert(0 &&
"Invalid SMT Commit Policy. Options Are: {Aggressive,"
145 "RoundRobin,OldestReady}");
163 template <
class Impl>
167 return cpu->name() +
".commit";
170 template <
class Impl>
179 template <
class Impl>
183 using namespace Stats;
185 .name(
name() +
".commitSquashedInsts")
186 .desc(
"The number of squashed insts skipped by commit")
187 .prereq(commitSquashedInsts);
190 .name(
name() +
".commitNonSpecStalls")
191 .desc(
"The number of times commit has been forced to stall to "
192 "communicate backwards")
193 .prereq(commitNonSpecStalls);
196 .name(
name() +
".branchMispredicts")
197 .desc(
"The number of times a branch was mispredicted")
198 .prereq(branchMispredicts);
201 .init(0,commitWidth,1)
202 .name(
name() +
".committed_per_cycle")
203 .desc(
"Number of insts commited each cycle")
208 .init(cpu->numThreads)
209 .name(
name() +
".committedInsts")
210 .desc(
"Number of instructions committed")
215 .init(cpu->numThreads)
216 .name(
name() +
".committedOps")
217 .desc(
"Number of ops (including micro ops) committed")
222 .init(cpu->numThreads)
223 .name(
name() +
".swp_count")
224 .desc(
"Number of s/w prefetches committed")
229 .init(cpu->numThreads)
230 .name(
name() +
".refs")
231 .desc(
"Number of memory references committed")
236 .init(cpu->numThreads)
237 .name(
name() +
".loads")
238 .desc(
"Number of loads committed")
243 .init(cpu->numThreads)
244 .name(
name() +
".membars")
245 .desc(
"Number of memory barriers committed")
250 .init(cpu->numThreads)
251 .name(
name() +
".branches")
252 .desc(
"Number of branches committed")
257 .init(cpu->numThreads)
258 .name(
name() +
".fp_insts")
259 .desc(
"Number of committed floating point instructions.")
264 .init(cpu->numThreads)
265 .name(
name()+
".int_insts")
266 .desc(
"Number of committed integer instructions.")
271 .init(cpu->numThreads)
272 .name(
name()+
".function_calls")
273 .desc(
"Number of function calls committed.")
277 statCommittedInstType
278 .init(numThreads,Enums::Num_OpClass)
279 .name(
name() +
".op_class")
280 .desc(
"Class of committed instruction")
283 statCommittedInstType.ysubnames(Enums::OpClassStrings);
285 commitEligibleSamples
286 .name(
name() +
".bw_lim_events")
287 .desc(
"number cycles where commit BW limit reached")
291 template <
class Impl>
298 template <
class Impl>
305 toIEW = timeBuffer->
getWire(0);
308 robInfoFromIEW = timeBuffer->getWire(-iewToCommitDelay);
311 template <
class Impl>
318 fromFetch = fetchQueue->
getWire(-fetchToCommitDelay);
321 template <
class Impl>
325 renameQueue = rq_ptr;
328 fromRename = renameQueue->
getWire(-renameToROBDelay);
331 template <
class Impl>
338 fromIEW = iewQueue->
getWire(-iewToCommitDelay);
341 template <
class Impl>
345 iewStage = iew_stage;
352 activeThreads = at_ptr;
355 template <
class Impl>
359 for (
ThreadID tid = 0; tid < numThreads; tid++)
360 renameMap[tid] = &rm_ptr[tid];
363 template <
class Impl>
370 template <
class Impl>
374 rob->setActiveThreads(activeThreads);
378 for (
ThreadID tid = 0; tid < numThreads; tid++) {
379 toIEW->commitInfo[tid].usedROB =
true;
380 toIEW->commitInfo[tid].freeROBEntries = rob->numFreeEntries(tid);
381 toIEW->commitInfo[tid].emptyROB =
true;
386 cpu->activateStage(O3CPU::CommitIdx);
388 cpu->activityThisCycle();
391 template <
class Impl>
398 template <
class Impl>
402 drainPending =
false;
403 drainImminent =
false;
406 template <
class Impl>
411 rob->drainSanityCheck();
414 template <
class Impl>
427 for (
ThreadID tid = 0; tid < numThreads; tid++) {
428 if (
pc[tid].microPC() != 0)
438 return rob->isEmpty() &&
442 template <
class Impl>
447 _nextStatus = Inactive;
448 for (
ThreadID tid = 0; tid < numThreads; tid++) {
449 commitStatus[tid] = Idle;
450 changedROBNumEntries[tid] =
false;
451 trapSquash[tid] =
false;
452 tcSquash[tid] =
false;
453 squashAfterInst[tid] = NULL;
458 template <
class Impl>
463 priority_list.end(), tid);
465 if (thread_it != priority_list.end()) {
466 priority_list.erase(thread_it);
471 template <
class Impl>
479 while (threads != end) {
482 changedROBNumEntries[tid] =
false;
485 if (commitStatus[tid] == TrapPending ||
486 commitStatus[tid] == FetchTrapPending) {
487 _nextStatus = Active;
491 if (_nextStatus == Inactive && _status == Active) {
492 DPRINTF(Activity,
"Deactivating stage.\n");
493 cpu->deactivateStage(O3CPU::CommitIdx);
494 }
else if (_nextStatus == Active && _status == Inactive) {
495 DPRINTF(Activity,
"Activating stage.\n");
496 cpu->activateStage(O3CPU::CommitIdx);
499 _status = _nextStatus;
502 template <
class Impl>
509 while (threads != end) {
512 if (changedROBNumEntries[tid]) {
520 template <
class Impl>
524 return rob->numFreeEntries(tid);
527 template <
class Impl>
531 DPRINTF(Commit,
"Generating trap event for [tid:%i]\n", tid);
536 cpu->syscallRetryLatency : trapLatency;
538 cpu->schedule(trap, cpu->clockEdge(latency));
539 trapInFlight[tid] =
true;
540 thread[tid]->trapPending =
true;
543 template <
class Impl>
547 assert(!trapInFlight[tid]);
548 DPRINTF(Commit,
"Generating TC squash event for [tid:%i]\n", tid);
550 tcSquash[tid] =
true;
553 template <
class Impl>
561 InstSeqNum squashed_inst = rob->isEmpty(tid) ?
562 lastCommitedSeqNum[tid] : rob->readHeadInst(tid)->seqNum - 1;
567 youngestSeqNum[tid] = lastCommitedSeqNum[tid];
569 rob->squash(squashed_inst, tid);
570 changedROBNumEntries[tid] =
true;
573 toIEW->commitInfo[tid].doneSeqNum = squashed_inst;
577 toIEW->commitInfo[tid].squash =
true;
581 toIEW->commitInfo[tid].robSquashing =
true;
583 toIEW->commitInfo[tid].mispredictInst = NULL;
584 toIEW->commitInfo[tid].squashInst = NULL;
586 toIEW->commitInfo[tid].pc =
pc[tid];
589 template <
class Impl>
595 DPRINTF(Commit,
"Squashing from trap, restarting at PC %s\n",
pc[tid]);
597 thread[tid]->trapPending =
false;
598 thread[tid]->noSquashFromTC =
false;
599 trapInFlight[tid] =
false;
601 trapSquash[tid] =
false;
603 commitStatus[tid] = ROBSquashing;
604 cpu->activityThisCycle();
607 template <
class Impl>
613 DPRINTF(Commit,
"Squashing from TC, restarting at PC %s\n",
pc[tid]);
615 thread[tid]->noSquashFromTC =
false;
616 assert(!thread[tid]->trapPending);
618 commitStatus[tid] = ROBSquashing;
619 cpu->activityThisCycle();
621 tcSquash[tid] =
false;
624 template <
class Impl>
628 DPRINTF(Commit,
"Squashing after squash after request, "
629 "restarting at PC %s\n",
pc[tid]);
635 toIEW->commitInfo[tid].squashInst = squashAfterInst[tid];
636 squashAfterInst[tid] = NULL;
638 commitStatus[tid] = ROBSquashing;
639 cpu->activityThisCycle();
642 template <
class Impl>
646 DPRINTF(Commit,
"Executing squash after for [tid:%i] inst [sn:%lli]\n",
647 tid, head_inst->seqNum);
649 assert(!squashAfterInst[tid] || squashAfterInst[tid] == head_inst);
650 commitStatus[tid] = SquashAfterPending;
651 squashAfterInst[tid] = head_inst;
654 template <
class Impl>
658 wroteToTimeBuffer =
false;
659 _nextStatus = Inactive;
661 if (activeThreads->empty())
669 while (threads != end) {
674 committedStores[tid] =
false;
676 if (commitStatus[tid] == ROBSquashing) {
678 if (rob->isDoneSquashing(tid)) {
681 DPRINTF(Commit,
"[tid:%u]: Still Squashing, cannot commit any"
682 " insts this cycle.\n", tid);
684 toIEW->commitInfo[tid].robSquashing =
true;
685 wroteToTimeBuffer =
true;
692 markCompletedInsts();
694 threads = activeThreads->begin();
696 while (threads != end) {
699 if (!rob->isEmpty(tid) && rob->readHeadInst(tid)->readyToCommit()) {
702 _nextStatus = Active;
706 DPRINTF(Commit,
"[tid:%i]: Instruction [sn:%lli] PC %s is head of"
707 " ROB and ready to commit\n",
708 tid, inst->seqNum, inst->pcState());
710 }
else if (!rob->isEmpty(tid)) {
713 ppCommitStall->notify(inst);
715 DPRINTF(Commit,
"[tid:%i]: Can't commit, Instruction [sn:%lli] PC "
716 "%s is head of ROB and not ready\n",
717 tid, inst->seqNum, inst->pcState());
720 DPRINTF(Commit,
"[tid:%i]: ROB has %d insts & %d free entries.\n",
721 tid, rob->countInsts(tid), rob->numFreeEntries(tid));
725 if (wroteToTimeBuffer) {
726 DPRINTF(Activity,
"Activity This Cycle.\n");
727 cpu->activityThisCycle();
733 template <
class Impl>
738 if (!cpu->checkInterrupts(cpu->tcBase(0))) {
739 DPRINTF(Commit,
"Pending interrupt is cleared by master before "
740 "it got handled. Restart fetching from the orig path.\n");
741 toIEW->commitInfo[0].clearInterrupt =
true;
743 avoidQuiesceLiveLock =
true;
749 if (canHandleInterrupts && cpu->instList.empty()) {
752 DPRINTF(Commit,
"Interrupt detected.\n");
755 toIEW->commitInfo[0].clearInterrupt =
true;
757 assert(!thread[0]->noSquashFromTC);
758 thread[0]->noSquashFromTC =
true;
761 cpu->checker->handlePendingInt();
767 cpu->processInterrupts(cpu->getInterrupts());
769 thread[0]->noSquashFromTC =
false;
771 commitStatus[0] = TrapPending;
778 avoidQuiesceLiveLock =
false;
780 DPRINTF(Commit,
"Interrupt pending: instruction is %sin "
781 "flight, ROB is %sempty\n",
782 canHandleInterrupts ?
"not " :
"",
783 cpu->instList.empty() ?
"" :
"not " );
787 template <
class Impl>
793 if (commitStatus[0] == TrapPending ||
interrupt || trapSquash[0] ||
794 tcSquash[0] || drainImminent)
809 toIEW->commitInfo[0].interruptPending =
true;
812 template <
class Impl>
818 if (cpu->checkInterrupts(cpu->tcBase(0)))
819 propagateInterrupt();
828 int num_squashing_threads = 0;
830 while (threads != end) {
835 if (trapSquash[tid]) {
836 assert(!tcSquash[tid]);
838 }
else if (tcSquash[tid]) {
839 assert(commitStatus[tid] != TrapPending);
841 }
else if (commitStatus[tid] == SquashAfterPending) {
845 squashFromSquashAfter(tid);
851 if (fromIEW->squash[tid] &&
852 commitStatus[tid] != TrapPending &&
853 fromIEW->squashedSeqNum[tid] <= youngestSeqNum[tid]) {
855 if (fromIEW->mispredictInst[tid]) {
857 "[tid:%i]: Squashing due to branch mispred PC:%#x [sn:%i]\n",
859 fromIEW->mispredictInst[tid]->instAddr(),
860 fromIEW->squashedSeqNum[tid]);
863 "[tid:%i]: Squashing due to order violation [sn:%i]\n",
864 tid, fromIEW->squashedSeqNum[tid]);
867 DPRINTF(Commit,
"[tid:%i]: Redirecting to PC %#x\n",
869 fromIEW->pc[tid].nextInstAddr());
871 commitStatus[tid] = ROBSquashing;
875 InstSeqNum squashed_inst = fromIEW->squashedSeqNum[tid];
877 if (fromIEW->includeSquashInst[tid]) {
883 youngestSeqNum[tid] = squashed_inst;
885 rob->squash(squashed_inst, tid);
886 changedROBNumEntries[tid] =
true;
888 toIEW->commitInfo[tid].doneSeqNum = squashed_inst;
890 toIEW->commitInfo[tid].squash =
true;
894 toIEW->commitInfo[tid].robSquashing =
true;
896 toIEW->commitInfo[tid].mispredictInst =
897 fromIEW->mispredictInst[tid];
898 toIEW->commitInfo[tid].branchTaken =
899 fromIEW->branchTaken[tid];
900 toIEW->commitInfo[tid].squashInst =
901 rob->findInst(tid, squashed_inst);
902 if (toIEW->commitInfo[tid].mispredictInst) {
903 if (toIEW->commitInfo[tid].mispredictInst->isUncondCtrl()) {
904 toIEW->commitInfo[tid].branchTaken =
true;
909 toIEW->commitInfo[tid].pc = fromIEW->pc[tid];
912 if (commitStatus[tid] == ROBSquashing) {
913 num_squashing_threads++;
919 if (num_squashing_threads) {
920 _nextStatus = Active;
923 if (num_squashing_threads != numThreads) {
932 threads = activeThreads->begin();
934 while (threads != end) {
937 if (changedROBNumEntries[tid]) {
938 toIEW->commitInfo[tid].usedROB =
true;
939 toIEW->commitInfo[tid].freeROBEntries = rob->numFreeEntries(tid);
941 wroteToTimeBuffer =
true;
942 changedROBNumEntries[tid] =
false;
943 if (rob->isEmpty(tid))
944 checkEmptyROB[tid] =
true;
955 if (checkEmptyROB[tid] && rob->isEmpty(tid) &&
956 !iewStage->hasStoresToWB(tid) && !committedStores[tid]) {
957 checkEmptyROB[tid] =
false;
958 toIEW->commitInfo[tid].usedROB =
true;
959 toIEW->commitInfo[tid].emptyROB =
true;
960 toIEW->commitInfo[tid].freeROBEntries = rob->numFreeEntries(tid);
961 wroteToTimeBuffer =
true;
967 template <
class Impl>
980 DPRINTF(Commit,
"Trying to commit instructions in the ROB.\n");
982 unsigned num_committed = 0;
988 while (num_committed < commitWidth) {
994 ThreadID commit_thread = getCommittingThread();
996 if (commit_thread == -1 || !rob->isHeadReady(commit_thread))
999 head_inst = rob->readHeadInst(commit_thread);
1001 ThreadID tid = head_inst->threadNumber;
1003 assert(tid == commit_thread);
1005 DPRINTF(Commit,
"Trying to commit head instruction, [sn:%i] [tid:%i]\n",
1006 head_inst->seqNum, tid);
1010 if (head_inst->isSquashed()) {
1012 DPRINTF(Commit,
"Retiring squashed instruction from "
1015 rob->retireHead(commit_thread);
1017 ++commitSquashedInsts;
1019 ppSquash->notify(head_inst);
1022 changedROBNumEntries[tid] =
true;
1024 pc[tid] = head_inst->pcState();
1031 thread[tid]->funcExeInst++;
1034 bool commit_success = commitHead(head_inst, num_committed);
1036 if (commit_success) {
1038 statCommittedInstType[tid][head_inst->opClass()]++;
1039 ppCommit->notify(head_inst);
1041 changedROBNumEntries[tid] =
true;
1044 toIEW->commitInfo[tid].doneSeqNum = head_inst->seqNum;
1047 canHandleInterrupts = (!head_inst->isDelayedCommit()) &&
1048 ((THE_ISA != ALPHA_ISA) ||
1049 (!(
pc[0].instAddr() & 0x3)));
1053 head_inst->updateMiscRegs();
1058 cpu->checker->verify(head_inst);
1061 cpu->traceFunctions(
pc[tid].instAddr());
1066 lastCommitedSeqNum[tid] = head_inst->seqNum;
1070 if (head_inst->isSquashAfter())
1071 squashAfter(tid, head_inst);
1075 !thread[tid]->trapPending) {
1079 DPRINTF(Drain,
"Draining: %i:%s\n", tid,
pc[tid]);
1080 squashAfter(tid, head_inst);
1081 cpu->commitDrained(tid);
1082 drainImminent =
true;
1086 bool onInstBoundary = !head_inst->isMicroop() ||
1087 head_inst->isLastMicroop() ||
1088 !head_inst->isDelayedCommit();
1090 if (onInstBoundary) {
1095 assert(!thread[tid]->noSquashFromTC &&
1096 !thread[tid]->trapPending);
1098 oldpc =
pc[tid].instAddr();
1099 cpu->system->pcEventQueue.service(thread[tid]->getTC());
1101 }
while (oldpc !=
pc[tid].instAddr());
1104 "PC skip function event, stopping commit\n");
1116 if (!
interrupt && avoidQuiesceLiveLock &&
1117 onInstBoundary && cpu->checkInterrupts(cpu->tcBase(0)))
1118 squashAfter(tid, head_inst);
1120 DPRINTF(Commit,
"Unable to commit head instruction PC:%s "
1121 "[tid:%i] [sn:%i].\n",
1122 head_inst->pcState(), tid ,head_inst->seqNum);
1128 DPRINTF(CommitRate,
"%i\n", num_committed);
1129 numCommittedDist.sample(num_committed);
1131 if (num_committed == commitWidth) {
1132 commitEligibleSamples++;
1136 template <
class Impl>
1142 ThreadID tid = head_inst->threadNumber;
1146 if (!head_inst->isExecuted()) {
1149 thread[tid]->funcExeInst--;
1153 assert(head_inst->isNonSpeculative() || head_inst->isStoreConditional()
1154 || head_inst->isMemBarrier() || head_inst->isWriteBarrier() ||
1155 (head_inst->isLoad() && head_inst->strictlyOrdered()));
1157 DPRINTF(Commit,
"Encountered a barrier or non-speculative "
1158 "instruction [sn:%lli] at the head of the ROB, PC %s.\n",
1159 head_inst->seqNum, head_inst->pcState());
1161 if (inst_num > 0 || iewStage->hasStoresToWB(tid)) {
1162 DPRINTF(Commit,
"Waiting for all stores to writeback.\n");
1166 toIEW->commitInfo[tid].nonSpecSeqNum = head_inst->seqNum;
1170 head_inst->clearCanCommit();
1172 if (head_inst->isLoad() && head_inst->strictlyOrdered()) {
1173 DPRINTF(Commit,
"[sn:%lli]: Strictly ordered load, PC %s.\n",
1174 head_inst->seqNum, head_inst->pcState());
1175 toIEW->commitInfo[tid].strictlyOrdered =
true;
1176 toIEW->commitInfo[tid].strictlyOrderedLoad = head_inst;
1178 ++commitNonSpecStalls;
1184 if (head_inst->isThreadSync()) {
1186 panic(
"Thread sync instructions are not handled yet.\n");
1190 Fault inst_fault = head_inst->getFault();
1193 if (!head_inst->isStore() && inst_fault ==
NoFault) {
1194 head_inst->setCompleted();
1198 DPRINTF(Commit,
"Inst [sn:%lli] PC %s has a fault\n",
1199 head_inst->seqNum, head_inst->pcState());
1201 if (iewStage->hasStoresToWB(tid) || inst_num > 0) {
1202 DPRINTF(Commit,
"Stores outstanding, fault must wait.\n");
1206 head_inst->setCompleted();
1212 cpu->checker->verify(head_inst);
1215 assert(!thread[tid]->noSquashFromTC);
1219 thread[tid]->noSquashFromTC =
true;
1227 cpu->trap(inst_fault, tid, head_inst->staticInst);
1230 thread[tid]->noSquashFromTC =
false;
1232 commitStatus[tid] = TrapPending;
1234 DPRINTF(Commit,
"Committing instruction with fault [sn:%lli]\n",
1236 if (head_inst->traceData) {
1237 if (
DTRACE(ExecFaulting)) {
1238 head_inst->traceData->setFetchSeq(head_inst->seqNum);
1239 head_inst->traceData->setCPSeq(thread[tid]->numOp);
1240 head_inst->traceData->dump();
1242 delete head_inst->traceData;
1243 head_inst->traceData = NULL;
1247 generateTrapEvent(tid, inst_fault);
1251 updateComInstStats(head_inst);
1254 if (thread[tid]->profile) {
1255 thread[tid]->profilePC = head_inst->instAddr();
1256 ProfileNode *node = thread[tid]->profile->consume(
1257 thread[tid]->getTC(), head_inst->staticInst);
1260 thread[tid]->profileNode = node;
1263 if (head_inst->isControl()) {
1269 DPRINTF(Commit,
"Committing instruction with [sn:%lli] PC %s\n",
1270 head_inst->seqNum, head_inst->pcState());
1271 if (head_inst->traceData) {
1272 head_inst->traceData->setFetchSeq(head_inst->seqNum);
1273 head_inst->traceData->setCPSeq(thread[tid]->numOp);
1274 head_inst->traceData->dump();
1275 delete head_inst->traceData;
1276 head_inst->traceData = NULL;
1278 if (head_inst->isReturn()) {
1279 DPRINTF(Commit,
"Return Instruction Committed [sn:%lli] PC %s \n",
1280 head_inst->seqNum, head_inst->pcState());
1284 for (
int i = 0;
i < head_inst->numDestRegs();
i++) {
1285 renameMap[tid]->setEntry(head_inst->flattenedDestRegIdx(
i),
1286 head_inst->renamedDestRegIdx(
i));
1290 rob->retireHead(tid);
1293 if (
DTRACE(O3PipeView)) {
1294 head_inst->commitTick =
curTick() - head_inst->fetchTick;
1299 if (head_inst->isStore())
1300 committedStores[tid] =
true;
1306 template <
class Impl>
1310 DPRINTF(Commit,
"Getting instructions from Rename stage.\n");
1313 int insts_to_process = std::min((
int)renameWidth, fromRename->size);
1315 for (
int inst_num = 0; inst_num < insts_to_process; ++inst_num) {
1318 inst = fromRename->insts[inst_num];
1321 if (!inst->isSquashed() &&
1322 commitStatus[tid] != ROBSquashing &&
1323 commitStatus[tid] != TrapPending) {
1324 changedROBNumEntries[tid] =
true;
1326 DPRINTF(Commit,
"Inserting PC %s [sn:%i] [tid:%i] into ROB.\n",
1327 inst->pcState(), inst->seqNum, tid);
1329 rob->insertInst(inst);
1331 assert(rob->getThreadEntries(tid) <= rob->getMaxEntries(tid));
1333 youngestSeqNum[tid] = inst->seqNum;
1335 DPRINTF(Commit,
"Instruction PC %s [sn:%i] [tid:%i] was "
1336 "squashed, skipping.\n",
1337 inst->pcState(), inst->seqNum, tid);
1342 template <
class Impl>
1348 for (
int inst_num = 0; inst_num < fromIEW->size; ++inst_num) {
1349 assert(fromIEW->insts[inst_num]);
1350 if (!fromIEW->insts[inst_num]->isSquashed()) {
1351 DPRINTF(Commit,
"[tid:%i]: Marking PC %s, [sn:%lli] ready "
1353 fromIEW->insts[inst_num]->threadNumber,
1354 fromIEW->insts[inst_num]->pcState(),
1355 fromIEW->insts[inst_num]->seqNum);
1358 fromIEW->insts[inst_num]->setCanCommit();
1363 template <
class Impl>
1369 if (!inst->isMicroop() || inst->isLastMicroop())
1370 instsCommitted[tid]++;
1371 opsCommitted[tid]++;
1375 if (!inst->isNop() && !inst->isInstPrefetch()) {
1376 cpu->instDone(tid, inst);
1382 if (inst->isControl())
1383 statComBranches[tid]++;
1388 if (inst->isMemRef()) {
1391 if (inst->isLoad()) {
1392 statComLoads[tid]++;
1396 if (inst->isMemBarrier()) {
1397 statComMembars[tid]++;
1401 if (inst->isInteger())
1402 statComInteger[tid]++;
1405 if (inst->isFloating())
1406 statComFloating[tid]++;
1410 statComFunctionCalls[tid]++;
1419 template <
class Impl>
1423 if (numThreads > 1) {
1424 switch (commitPolicy) {
1430 return oldestReady();
1433 return roundRobin();
1436 return oldestReady();
1442 assert(!activeThreads->empty());
1443 ThreadID tid = activeThreads->front();
1445 if (commitStatus[tid] ==
Running ||
1446 commitStatus[tid] == Idle ||
1447 commitStatus[tid] == FetchTrapPending) {
1455 template<
class Impl>
1462 while (pri_iter != end) {
1465 if (commitStatus[tid] ==
Running ||
1466 commitStatus[tid] == Idle ||
1467 commitStatus[tid] == FetchTrapPending) {
1469 if (rob->isHeadReady(tid)) {
1470 priority_list.erase(pri_iter);
1471 priority_list.push_back(tid);
1483 template<
class Impl>
1487 unsigned oldest = 0;
1493 while (threads != end) {
1496 if (!rob->isEmpty(tid) &&
1497 (commitStatus[tid] ==
Running ||
1498 commitStatus[tid] == Idle ||
1499 commitStatus[tid] == FetchTrapPending)) {
1501 if (rob->isHeadReady(tid)) {
1503 DynInstPtr head_inst = rob->readHeadInst(tid);
1508 }
else if (head_inst->seqNum < oldest) {
1522 #endif//__CPU_O3_COMMIT_IMPL_HH__
const unsigned commitWidth
Commit width, in instructions.
const FlagsType pdf
Print the percent of the total that this entry represents.
void handleInterrupt()
Handles processing an interrupt.
void regProbePoints()
Registers probes.
const Cycles fetchToCommitDelay
decltype(nullptr) constexpr NoFault
Cycles is a wrapper class for representing cycle counts, i.e.
void setRenameMap(RenameMap rm_ptr[Impl::MaxThreads])
Sets pointer to the commited state rename map.
bool trapInFlight[Impl::MaxThreads]
Records if there is a trap currently in flight.
const std::string & name()
TheISA::PCState pc[Impl::MaxThreads]
The commit PC state of each thread.
bool drainImminent
Is a drain imminent? Commit has found an instruction boundary while no interrupts were present or in ...
void squashFromTC(ThreadID tid)
Handles squashing due to an TC write.
const Cycles renameToROBDelay
Rename to ROB delay.
CPUPol::RenameMap RenameMap
const Cycles commitToIEWDelay
Commit to IEW delay.
bool FullSystem
The FullSystem variable can be used to determine the current mode of simulation.
void squashFromSquashAfter(ThreadID tid)
Handles a squash from a squashAfter() request.
void setActiveThreads(std::list< ThreadID > *at_ptr)
Sets pointer to list of active threads.
void setTimeBuffer(TimeBuffer< TimeStruct > *tb_ptr)
Sets the main time buffer pointer, used for backwards communication.
bool tcSquash[Impl::MaxThreads]
Records if a thread has to squash this cycle due to an XC write.
void updateStatus()
Updates the overall status of commit with the nextStatus, and tell the CPU if commit is active/inacti...
bool isDrained() const
Has the stage drained?
void getInsts()
Gets instructions from rename and inserts them into the ROB.
void setRenameQueue(TimeBuffer< RenameStruct > *rq_ptr)
Sets the pointer to the queue coming from rename.
std::string name() const
Returns the name of the DefaultCommit.
bool avoidQuiesceLiveLock
Have we had an interrupt pending and then seen it de-asserted because of a masking change...
DefaultCommit(O3CPU *_cpu, DerivO3CPUParams *params)
Construct a DefaultCommit with the given parameters.
ThreadContext is the external interface to all thread state for anything outside of the CPU...
void tick()
Ticks the commit stage, which tries to commit instructions.
ThreadID roundRobin()
Returns the thread ID to use based on a round robin policy.
void commitInsts()
Commits as many instructions as possible.
DefaultCommit handles single threaded and SMT commit.
void setIEWStage(IEW *iew_stage)
Sets the pointer to the IEW stage.
void drainResume()
Resumes execution after draining.
void propagateInterrupt()
Get fetch redirecting so we can handle an interrupt.
void swAutoBegin(ThreadContext *tc, Addr next_pc)
void generateTrapEvent(ThreadID tid, Fault inst_fault)
Generates an event to schedule a squash due to a trap.
const Cycles trapLatency
The latency to handle a trap.
Tick curTick()
The current simulated tick.
void setFetchQueue(TimeBuffer< FetchStruct > *fq_ptr)
void squashFromTrap(ThreadID tid)
Handles squashing due to a trap.
const unsigned renameWidth
Rename width, in instructions.
ThreadID oldestReady()
Returns the thread ID to use based on an oldest instruction policy.
void setThreads(std::vector< Thread * > &threads)
Sets the list of threads.
ThreadStatus commitStatus[Impl::MaxThreads]
Per-thread status.
virtual Addr nextInstAddr()=0
void squashAll(ThreadID tid)
Squashes all in flight instructions.
void generateTCEvent(ThreadID tid)
Records that commit needs to initiate a squash due to an external state update through the TC...
O3CPU * cpu
Pointer to O3CPU.
void squashAfter(ThreadID tid, DynInstPtr &head_inst)
Handle squashing from instruction with SquashAfter set.
void regStats()
Registers statistics.
void deactivateThread(ThreadID tid)
Deschedules a thread from scheduling.
void setROB(ROB *rob_ptr)
Sets pointer to the ROB.
bool checkEmptyROB[Impl::MaxThreads]
Records if commit should check if the ROB is truly empty (see commit_impl.hh).
Fault interrupt
The interrupt fault.
uint64_t Addr
Address type This will probably be moved somewhere else in the near future.
void takeOverFrom()
Takes over from another CPU's thread.
void advancePC(PCState &pc, const StaticInstPtr &inst)
const Cycles iewToCommitDelay
IEW to Commit delay.
bool changedROBEntries()
Returns if any of the threads have the number of ROB entries changed on this cycle.
bool drainPending
Is a drain pending? Commit is looking for an instruction boundary while there are no pending interrup...
const FlagsType total
Print the total.
CommitPolicy commitPolicy
Commit policy used in SMT mode.
const ThreadID InvalidThreadID
void drain()
Initializes the draining of commit.
size_t numROBFreeEntries(ThreadID tid)
Returns the number of free ROB entries for a specific thread.
int16_t ThreadID
Thread index/ID type.
InstSeqNum lastCommitedSeqNum[Impl::MaxThreads]
The sequence number of the last commited instruction.
void drainSanityCheck() const
Perform sanity checks after a drain.
std::list< ThreadID > priority_list
Priority List used for Commit Policy.
bool trapSquash[Impl::MaxThreads]
Records if a thread has to squash this cycle due to a trap.
void commit()
Handles any squashes that are sent from IEW, and adds instructions to the ROB and tries to commit ins...
const ThreadID numThreads
Number of Active Threads.
void updateComInstStats(DynInstPtr &inst)
Updates commit stats based on this instruction.
ThreadID getCommittingThread()
Gets the thread to commit, based on the SMT policy.
void setIEWQueue(TimeBuffer< IEWStruct > *iq_ptr)
Sets the pointer to the queue coming from IEW.
bool committedStores[Impl::MaxThreads]
Records if there were any stores committed this cycle.
TrapEvent(DefaultCommit< Impl > *_commit, ThreadID _tid)
DynInstPtr squashAfterInst[Impl::MaxThreads]
Instruction passed to squashAfter().
const char * description() const
Return a C string describing the event.
Event class used to schedule a squash due to a trap (fault or interrupt) to happen on a specific cycl...
CommitStatus _nextStatus
Next commit status, to be set at the end of the cycle.
Impl::DynInstPtr DynInstPtr
const FlagsType dist
Print the distribution.
std::shared_ptr< FaultBase > Fault
bool commitHead(DynInstPtr &head_inst, unsigned inst_num)
Tries to commit the head ROB instruction passed in.
CommitStatus _status
Overall commit status.
bool canHandleInterrupts
True if last committed microop can be followed by an interrupt.
void startupStage()
Initializes stage by sending back the number of free entries.
bool changedROBNumEntries[Impl::MaxThreads]
Records if the number of ROB entries has changed this cycle.
void markCompletedInsts()
Marks completed instructions using information sent from IEW.