45 #ifndef __CPU_O3_INST_QUEUE_IMPL_HH__
46 #define __CPU_O3_INST_QUEUE_IMPL_HH__
53 #include "debug/IQ.hh"
54 #include "enums/OpClass.hh"
55 #include "params/DerivO3CPU.hh"
65 :
Event(Stat_Event_Pri, AutoDelete),
66 inst(_inst), fuIdx(fu_idx), iqPtr(iq_ptr), freeFU(false)
74 iqPtr->processFUCompletion(inst, freeFU ? fuIdx : -1);
83 return "Functional unit completion";
88 DerivO3CPUParams *params)
101 numPhysRegs = params->numPhysIntRegs + params->numPhysFloatRegs +
102 params->numPhysCCRegs;
119 std::string policy = params->smtIQPolicy;
122 std::transform(policy.begin(), policy.end(), policy.begin(),
123 (int(*)(int)) tolower);
126 if (policy ==
"dynamic") {
134 }
else if (policy ==
"partitioned") {
145 DPRINTF(IQ,
"IQ sharing policy set to Partitioned:"
146 "%i entries per thread.\n",part_amt);
147 }
else if (policy ==
"threshold") {
150 double threshold = (double)params->smtIQThreshold / 100;
152 int thresholdIQ = (
int)((double)threshold *
numEntries);
159 DPRINTF(IQ,
"IQ sharing policy set to Threshold:"
160 "%i entries per thread.\n",thresholdIQ);
162 assert(0 &&
"Invalid IQ Sharing Policy.Options Are:{Dynamic,"
163 "Partitioned, Threshold}");
167 template <
class Impl>
172 cprintf(
"Nodes traversed: %i, removed: %i\n",
173 dependGraph.nodesTraversed, dependGraph.nodesRemoved);
177 template <
class Impl>
181 return cpu->name() +
".iq";
184 template <
class Impl>
188 using namespace Stats;
190 .name(
name() +
".iqInstsAdded")
191 .desc(
"Number of instructions added to the IQ (excludes non-spec)")
192 .prereq(iqInstsAdded);
195 .name(
name() +
".iqNonSpecInstsAdded")
196 .desc(
"Number of non-speculative instructions added to the IQ")
197 .prereq(iqNonSpecInstsAdded);
200 .name(
name() +
".iqInstsIssued")
201 .desc(
"Number of instructions issued")
202 .prereq(iqInstsIssued);
205 .name(
name() +
".iqIntInstsIssued")
206 .desc(
"Number of integer instructions issued")
207 .prereq(iqIntInstsIssued);
210 .name(
name() +
".iqFloatInstsIssued")
211 .desc(
"Number of float instructions issued")
212 .prereq(iqFloatInstsIssued);
215 .name(
name() +
".iqBranchInstsIssued")
216 .desc(
"Number of branch instructions issued")
217 .prereq(iqBranchInstsIssued);
220 .name(
name() +
".iqMemInstsIssued")
221 .desc(
"Number of memory instructions issued")
222 .prereq(iqMemInstsIssued);
225 .name(
name() +
".iqMiscInstsIssued")
226 .desc(
"Number of miscellaneous instructions issued")
227 .prereq(iqMiscInstsIssued);
229 iqSquashedInstsIssued
230 .name(
name() +
".iqSquashedInstsIssued")
231 .desc(
"Number of squashed instructions issued")
232 .prereq(iqSquashedInstsIssued);
234 iqSquashedInstsExamined
235 .name(
name() +
".iqSquashedInstsExamined")
236 .desc(
"Number of squashed instructions iterated over during squash;"
237 " mainly for profiling")
238 .prereq(iqSquashedInstsExamined);
240 iqSquashedOperandsExamined
241 .name(
name() +
".iqSquashedOperandsExamined")
242 .desc(
"Number of squashed operands that are examined and possibly "
243 "removed from graph")
244 .prereq(iqSquashedOperandsExamined);
246 iqSquashedNonSpecRemoved
247 .name(
name() +
".iqSquashedNonSpecRemoved")
248 .desc(
"Number of squashed non-spec instructions that were removed")
249 .prereq(iqSquashedNonSpecRemoved);
262 .init(0,totalWidth,1)
263 .name(
name() +
".issued_per_cycle")
264 .desc(
"Number of insts issued each cycle")
279 .init(numThreads,Enums::Num_OpClass)
280 .name(
name() +
".FU_type")
281 .desc(
"Type of FU issued")
284 statIssuedInstType.ysubnames(Enums::OpClassStrings);
304 .name(
name() +
".rate")
305 .desc(
"Inst issue rate")
308 issueRate = iqInstsIssued / cpu->numCycles;
312 .name(
name() +
".fu_full")
313 .desc(
"attempts to use FU when none available")
317 statFuBusy.subname(
i, Enums::OpClassStrings[
i]);
322 .name(
name() +
".fu_busy_cnt")
323 .desc(
"FU busy when requested")
328 .name(
name() +
".fu_busy_rate")
329 .desc(
"FU busy rate (busy events/executed inst)")
332 fuBusyRate = fuBusy / iqInstsIssued;
334 for (
ThreadID tid = 0; tid < numThreads; tid++) {
336 memDepUnit[tid].regStats();
340 .name(
name() +
".int_inst_queue_reads")
341 .desc(
"Number of integer instruction queue reads")
345 .name(
name() +
".int_inst_queue_writes")
346 .desc(
"Number of integer instruction queue writes")
349 intInstQueueWakeupAccesses
350 .name(
name() +
".int_inst_queue_wakeup_accesses")
351 .desc(
"Number of integer instruction queue wakeup accesses")
355 .name(
name() +
".fp_inst_queue_reads")
356 .desc(
"Number of floating instruction queue reads")
360 .name(
name() +
".fp_inst_queue_writes")
361 .desc(
"Number of floating instruction queue writes")
364 fpInstQueueWakeupQccesses
365 .name(
name() +
".fp_inst_queue_wakeup_accesses")
366 .desc(
"Number of floating instruction queue wakeup accesses")
370 .name(
name() +
".int_alu_accesses")
371 .desc(
"Number of integer alu accesses")
375 .name(
name() +
".fp_alu_accesses")
376 .desc(
"Number of floating point alu accesses")
381 template <
class Impl>
386 for (
ThreadID tid = 0; tid <numThreads; tid++) {
388 instList[tid].clear();
392 freeEntries = numEntries;
399 for (
int i = 0;
i < numPhysRegs; ++
i) {
400 regScoreboard[
i] =
false;
403 for (
ThreadID tid = 0; tid < numThreads; ++tid) {
404 squashedSeqNum[tid] = 0;
408 while (!readyInsts[
i].empty())
410 queueOnList[
i] =
false;
411 readyIt[
i] = listOrder.end();
413 nonSpecInsts.clear();
415 deferredMemInsts.clear();
416 blockedMemInsts.clear();
417 retryMemInsts.clear();
421 template <
class Impl>
425 activeThreads = at_ptr;
428 template <
class Impl>
432 issueToExecuteQueue = i2e_ptr;
435 template <
class Impl>
441 fromCommit = timeBuffer->
getWire(-commitToIEWDelay);
444 template <
class Impl>
448 bool drained = dependGraph.empty() &&
449 instsToExecute.empty() &&
451 for (
ThreadID tid = 0; tid < numThreads; ++tid)
452 drained = drained && memDepUnit[tid].isDrained();
457 template <
class Impl>
461 assert(dependGraph.empty());
462 assert(instsToExecute.empty());
463 for (
ThreadID tid = 0; tid < numThreads; ++tid)
464 memDepUnit[tid].drainSanityCheck();
467 template <
class Impl>
474 template <
class Impl>
478 if (iqPolicy == Partitioned) {
479 return numEntries / num_threads;
486 template <
class Impl>
490 if (iqPolicy != Dynamic || numThreads > 1) {
491 int active_threads = activeThreads->size();
496 while (threads != end) {
499 if (iqPolicy == Partitioned) {
500 maxEntries[tid] = numEntries / active_threads;
501 }
else if (iqPolicy == Threshold && active_threads == 1) {
502 maxEntries[tid] = numEntries;
508 template <
class Impl>
515 template <
class Impl>
519 return maxEntries[tid] -
count[tid];
524 template <
class Impl>
528 if (freeEntries == 0) {
535 template <
class Impl>
539 if (numFreeEntries(tid) == 0) {
546 template <
class Impl>
550 if (!listOrder.empty()) {
555 if (!readyInsts[
i].empty()) {
563 template <
class Impl>
567 new_inst->isFloating() ? fpInstQueueWrites++ : intInstQueueWrites++;
571 DPRINTF(IQ,
"Adding instruction [sn:%lli] PC %s to the IQ.\n",
572 new_inst->seqNum, new_inst->pcState());
574 assert(freeEntries != 0);
576 instList[new_inst->threadNumber].push_back(new_inst);
584 addToDependents(new_inst);
588 addToProducers(new_inst);
590 if (new_inst->isMemRef()) {
591 memDepUnit[new_inst->threadNumber].insert(new_inst);
593 addIfReady(new_inst);
598 count[new_inst->threadNumber]++;
600 assert(freeEntries == (numEntries - countInsts()));
603 template <
class Impl>
609 new_inst->isFloating() ? fpInstQueueWrites++ : intInstQueueWrites++;
613 nonSpecInsts[new_inst->seqNum] = new_inst;
615 DPRINTF(IQ,
"Adding non-speculative instruction [sn:%lli] PC %s "
617 new_inst->seqNum, new_inst->pcState());
619 assert(freeEntries != 0);
621 instList[new_inst->threadNumber].push_back(new_inst);
629 addToProducers(new_inst);
633 if (new_inst->isMemRef()) {
634 memDepUnit[new_inst->threadNumber].insertNonSpec(new_inst);
637 ++iqNonSpecInstsAdded;
639 count[new_inst->threadNumber]++;
641 assert(freeEntries == (numEntries - countInsts()));
644 template <
class Impl>
648 memDepUnit[barr_inst->threadNumber].insertBarrier(barr_inst);
650 insertNonSpec(barr_inst);
653 template <
class Impl>
654 typename Impl::DynInstPtr
657 assert(!instsToExecute.empty());
659 instsToExecute.pop_front();
660 if (inst->isFloating()){
668 template <
class Impl>
672 assert(!readyInsts[op_class].empty());
678 queue_entry.
oldestInst = readyInsts[op_class].top()->seqNum;
683 while (list_it != list_end_it) {
684 if ((*list_it).oldestInst > queue_entry.
oldestInst) {
691 readyIt[op_class] = listOrder.insert(list_it, queue_entry);
692 queueOnList[op_class] =
true;
695 template <
class Impl>
705 OpClass op_class = (*list_order_it).
queueType;
711 queue_entry.
oldestInst = readyInsts[op_class].top()->seqNum;
713 while (next_it != listOrder.end() &&
714 (*next_it).oldestInst < queue_entry.
oldestInst) {
718 readyIt[op_class] = listOrder.insert(next_it, queue_entry);
721 template <
class Impl>
725 DPRINTF(IQ,
"Processing FU completion [sn:%lli]\n", inst->seqNum);
726 assert(!cpu->switchedOut());
733 fuPool->freeUnitNextCycle(fu_idx);
738 issueToExecuteQueue->access(-1)->size++;
739 instsToExecute.push_back(inst);
745 template <
class Impl>
749 DPRINTF(IQ,
"Attempting to schedule ready instructions from "
752 IssueStruct *i2e_info = issueToExecuteQueue->access(0);
755 while (mem_inst = getDeferredMemInstToExecute()) {
756 addReadyMemInst(mem_inst);
760 while (mem_inst = getBlockedMemInstToExecute()) {
761 addReadyMemInst(mem_inst);
772 int total_issued = 0;
776 while (total_issued < totalWidth && order_it != order_end_it) {
777 OpClass op_class = (*order_it).queueType;
779 assert(!readyInsts[op_class].empty());
781 DynInstPtr issuing_inst = readyInsts[op_class].top();
783 issuing_inst->isFloating() ? fpInstQueueReads++ : intInstQueueReads++;
785 assert(issuing_inst->seqNum == (*order_it).oldestInst);
787 if (issuing_inst->isSquashed()) {
788 readyInsts[op_class].pop();
790 if (!readyInsts[op_class].empty()) {
791 moveToYoungerInst(order_it);
793 readyIt[op_class] = listOrder.end();
794 queueOnList[op_class] =
false;
797 listOrder.erase(order_it++);
799 ++iqSquashedInstsIssued;
806 ThreadID tid = issuing_inst->threadNumber;
808 if (op_class != No_OpClass) {
809 idx = fuPool->getUnit(op_class);
810 issuing_inst->isFloating() ? fpAluAccesses++ : intAluAccesses++;
812 op_latency = fuPool->getOpLatency(op_class);
819 if (op_latency ==
Cycles(1)) {
821 instsToExecute.push_back(issuing_inst);
826 fuPool->freeUnitNextCycle(idx);
828 bool pipelined = fuPool->isPipelined(op_class);
834 cpu->schedule(execution,
835 cpu->clockEdge(
Cycles(op_latency - 1)));
843 fuPool->freeUnitNextCycle(idx);
847 DPRINTF(IQ,
"Thread %i: Issuing instruction PC %s "
849 tid, issuing_inst->pcState(),
850 issuing_inst->seqNum);
852 readyInsts[op_class].pop();
854 if (!readyInsts[op_class].empty()) {
855 moveToYoungerInst(order_it);
857 readyIt[op_class] = listOrder.end();
858 queueOnList[op_class] =
false;
861 issuing_inst->setIssued();
865 issuing_inst->issueTick =
curTick() - issuing_inst->fetchTick;
868 if (!issuing_inst->isMemRef()) {
873 issuing_inst->clearInIQ();
875 memDepUnit[tid].issue(issuing_inst);
878 listOrder.erase(order_it++);
879 statIssuedInstType[tid][op_class]++;
881 statFuBusy[op_class]++;
887 numIssuedDist.sample(total_issued);
888 iqInstsIssued+= total_issued;
894 if (total_issued || !retryMemInsts.empty() || !deferredMemInsts.empty()) {
895 cpu->activityThisCycle();
897 DPRINTF(IQ,
"Not able to schedule any instructions.\n");
901 template <
class Impl>
905 DPRINTF(IQ,
"Marking nonspeculative instruction [sn:%lli] as ready "
906 "to execute.\n", inst);
910 assert(inst_it != nonSpecInsts.end());
912 ThreadID tid = (*inst_it).second->threadNumber;
914 (*inst_it).second->setAtCommit();
916 (*inst_it).second->setCanIssue();
918 if (!(*inst_it).second->isMemRef()) {
919 addIfReady((*inst_it).second);
921 memDepUnit[tid].nonSpecInstReady((*inst_it).second);
924 (*inst_it).second = NULL;
926 nonSpecInsts.erase(inst_it);
929 template <
class Impl>
933 DPRINTF(IQ,
"[tid:%i]: Committing instructions older than [sn:%i]\n",
936 ListIt iq_it = instList[tid].begin();
938 while (iq_it != instList[tid].end() &&
939 (*iq_it)->seqNum <= inst) {
941 instList[tid].pop_front();
944 assert(freeEntries == (numEntries - countInsts()));
947 template <
class Impl>
954 if (completed_inst->isFloating()) {
955 fpInstQueueWakeupQccesses++;
957 intInstQueueWakeupAccesses++;
960 DPRINTF(IQ,
"Waking dependents of completed instruction.\n");
962 assert(!completed_inst->isSquashed());
970 if (completed_inst->isMemRef()) {
971 memDepUnit[completed_inst->threadNumber].wakeDependents(completed_inst);
972 completeMemInst(completed_inst);
973 }
else if (completed_inst->isMemBarrier() ||
974 completed_inst->isWriteBarrier()) {
975 memDepUnit[completed_inst->threadNumber].completeBarrier(completed_inst);
978 for (
int dest_reg_idx = 0;
979 dest_reg_idx < completed_inst->numDestRegs();
983 completed_inst->renamedDestRegIdx(dest_reg_idx);
988 if (dest_reg >= numPhysRegs) {
989 DPRINTF(IQ,
"dest_reg :%d, numPhysRegs: %d\n", dest_reg,
994 DPRINTF(IQ,
"Waking any dependents on register %i.\n",
999 DynInstPtr dep_inst = dependGraph.pop(dest_reg);
1002 DPRINTF(IQ,
"Waking up a dependent instruction, [sn:%lli] "
1003 "PC %s.\n", dep_inst->seqNum, dep_inst->pcState());
1009 dep_inst->markSrcRegReady();
1011 addIfReady(dep_inst);
1013 dep_inst = dependGraph.pop(dest_reg);
1020 assert(dependGraph.empty(dest_reg));
1021 dependGraph.clearInst(dest_reg);
1024 regScoreboard[dest_reg] =
true;
1029 template <
class Impl>
1033 OpClass op_class = ready_inst->opClass();
1035 readyInsts[op_class].push(ready_inst);
1039 if (!queueOnList[op_class]) {
1040 addToOrderList(op_class);
1041 }
else if (readyInsts[op_class].top()->seqNum <
1042 (*readyIt[op_class]).oldestInst) {
1043 listOrder.erase(readyIt[op_class]);
1044 addToOrderList(op_class);
1047 DPRINTF(IQ,
"Instruction is ready to issue, putting it onto "
1048 "the ready list, PC %s opclass:%i [sn:%lli].\n",
1049 ready_inst->pcState(), op_class, ready_inst->seqNum);
1052 template <
class Impl>
1056 DPRINTF(IQ,
"Rescheduling mem inst [sn:%lli]\n", resched_inst->seqNum);
1059 resched_inst->translationStarted(
false);
1060 resched_inst->translationCompleted(
false);
1062 resched_inst->clearCanIssue();
1063 memDepUnit[resched_inst->threadNumber].reschedule(resched_inst);
1066 template <
class Impl>
1070 memDepUnit[replay_inst->threadNumber].replay();
1073 template <
class Impl>
1077 ThreadID tid = completed_inst->threadNumber;
1079 DPRINTF(IQ,
"Completing mem instruction PC: %s [sn:%lli]\n",
1080 completed_inst->pcState(), completed_inst->seqNum);
1084 completed_inst->memOpDone(
true);
1086 memDepUnit[tid].completed(completed_inst);
1090 template <
class Impl>
1094 deferredMemInsts.push_back(deferred_inst);
1097 template <
class Impl>
1101 blocked_inst->translationStarted(
false);
1102 blocked_inst->translationCompleted(
false);
1104 blocked_inst->clearIssued();
1105 blocked_inst->clearCanIssue();
1106 blockedMemInsts.push_back(blocked_inst);
1109 template <
class Impl>
1113 retryMemInsts.splice(retryMemInsts.end(), blockedMemInsts);
1118 template <
class Impl>
1119 typename Impl::DynInstPtr
1122 for (
ListIt it = deferredMemInsts.begin(); it != deferredMemInsts.end();
1124 if ((*it)->translationCompleted() || (*it)->isSquashed()) {
1126 deferredMemInsts.erase(it);
1133 template <
class Impl>
1134 typename Impl::DynInstPtr
1137 if (retryMemInsts.empty()) {
1141 retryMemInsts.pop_front();
1146 template <
class Impl>
1151 intInstQueueWrites++;
1152 memDepUnit[store->threadNumber].violation(store, faulting_load);
1155 template <
class Impl>
1159 DPRINTF(IQ,
"[tid:%i]: Starting to squash instructions in "
1164 squashedSeqNum[tid] = fromCommit->commitInfo[tid].doneSeqNum;
1169 memDepUnit[tid].squash(squashedSeqNum[tid], tid);
1172 template <
class Impl>
1177 ListIt squash_it = instList[tid].end();
1180 DPRINTF(IQ,
"[tid:%i]: Squashing until sequence number %i!\n",
1181 tid, squashedSeqNum[tid]);
1185 while (squash_it != instList[tid].end() &&
1186 (*squash_it)->seqNum > squashedSeqNum[tid]) {
1189 squashed_inst->isFloating() ? fpInstQueueWrites++ : intInstQueueWrites++;
1193 if (squashed_inst->threadNumber != tid ||
1194 squashed_inst->isSquashedInIQ()) {
1199 if (!squashed_inst->isIssued() ||
1200 (squashed_inst->isMemRef() &&
1201 !squashed_inst->memOpDone())) {
1203 DPRINTF(IQ,
"[tid:%i]: Instruction [sn:%lli] PC %s squashed.\n",
1204 tid, squashed_inst->seqNum, squashed_inst->pcState());
1206 bool is_acq_rel = squashed_inst->isMemBarrier() &&
1207 (squashed_inst->isLoad() ||
1208 (squashed_inst->isStore() &&
1209 !squashed_inst->isStoreConditional()));
1213 (!squashed_inst->isNonSpeculative() &&
1214 !squashed_inst->isStoreConditional() &&
1215 !squashed_inst->isMemBarrier() &&
1216 !squashed_inst->isWriteBarrier())) {
1218 for (
int src_reg_idx = 0;
1219 src_reg_idx < squashed_inst->numSrcRegs();
1223 squashed_inst->renamedSrcRegIdx(src_reg_idx);
1234 if (!squashed_inst->isReadySrcRegIdx(src_reg_idx) &&
1235 src_reg < numPhysRegs) {
1236 dependGraph.remove(src_reg, squashed_inst);
1240 ++iqSquashedOperandsExamined;
1242 }
else if (!squashed_inst->isStoreConditional() ||
1243 !squashed_inst->isCompleted()) {
1245 nonSpecInsts.find(squashed_inst->seqNum);
1250 if (ns_inst_it == nonSpecInsts.end()) {
1254 assert(squashed_inst->getFault() !=
NoFault ||
1255 squashed_inst->isMemRef());
1258 (*ns_inst_it).second = NULL;
1260 nonSpecInsts.erase(ns_inst_it);
1262 ++iqSquashedNonSpecRemoved;
1269 squashed_inst->setSquashedInIQ();
1273 squashed_inst->setIssued();
1274 squashed_inst->setCanCommit();
1275 squashed_inst->clearInIQ();
1278 count[squashed_inst->threadNumber]--;
1283 instList[tid].erase(squash_it--);
1284 ++iqSquashedInstsExamined;
1288 template <
class Impl>
1294 int8_t total_src_regs = new_inst->numSrcRegs();
1295 bool return_val =
false;
1297 for (
int src_reg_idx = 0;
1298 src_reg_idx < total_src_regs;
1302 if (!new_inst->isReadySrcRegIdx(src_reg_idx)) {
1303 PhysRegIndex src_reg = new_inst->renamedSrcRegIdx(src_reg_idx);
1309 if (src_reg >= numPhysRegs) {
1311 }
else if (!regScoreboard[src_reg]) {
1312 DPRINTF(IQ,
"Instruction PC %s has src reg %i that "
1313 "is being added to the dependency chain.\n",
1314 new_inst->pcState(), src_reg);
1316 dependGraph.insert(src_reg, new_inst);
1322 DPRINTF(IQ,
"Instruction PC %s has src reg %i that "
1323 "became ready before it reached the IQ.\n",
1324 new_inst->pcState(), src_reg);
1326 new_inst->markSrcRegReady(src_reg_idx);
1334 template <
class Impl>
1342 int8_t total_dest_regs = new_inst->numDestRegs();
1344 for (
int dest_reg_idx = 0;
1345 dest_reg_idx < total_dest_regs;
1348 PhysRegIndex dest_reg = new_inst->renamedDestRegIdx(dest_reg_idx);
1354 if (dest_reg >= numPhysRegs) {
1358 if (!dependGraph.empty(dest_reg)) {
1360 panic(
"Dependency graph %i not empty!", dest_reg);
1363 dependGraph.setInst(dest_reg, new_inst);
1366 regScoreboard[dest_reg] =
false;
1370 template <
class Impl>
1376 if (inst->readyToIssue()) {
1379 if (inst->isMemRef()) {
1381 DPRINTF(IQ,
"Checking if memory instruction can issue.\n");
1385 memDepUnit[inst->threadNumber].regsReady(inst);
1390 OpClass op_class = inst->opClass();
1392 DPRINTF(IQ,
"Instruction is ready to issue, putting it onto "
1393 "the ready list, PC %s opclass:%i [sn:%lli].\n",
1394 inst->pcState(), op_class, inst->seqNum);
1396 readyInsts[op_class].push(inst);
1400 if (!queueOnList[op_class]) {
1401 addToOrderList(op_class);
1402 }
else if (readyInsts[op_class].top()->seqNum <
1403 (*readyIt[op_class]).oldestInst) {
1404 listOrder.erase(readyIt[op_class]);
1405 addToOrderList(op_class);
1410 template <
class Impl>
1419 int total_insts = 0;
1421 for (
ThreadID tid = 0; tid < numThreads; ++tid) {
1422 ListIt count_it = instList[tid].begin();
1424 while (count_it != instList[tid].end()) {
1425 if (!(*count_it)->isSquashed() && !(*count_it)->isSquashedInIQ()) {
1426 if (!(*count_it)->isIssued()) {
1428 }
else if ((*count_it)->isMemRef() &&
1429 !(*count_it)->memOpDone) {
1442 return numEntries - freeEntries;
1446 template <
class Impl>
1451 cprintf(
"Ready list %i size: %i\n",
i, readyInsts[
i].
size());
1456 cprintf(
"Non speculative list size: %i\n", nonSpecInsts.size());
1461 cprintf(
"Non speculative list: ");
1463 while (non_spec_it != non_spec_end_it) {
1464 cprintf(
"%s [sn:%lli]", (*non_spec_it).second->pcState(),
1465 (*non_spec_it).second->seqNum);
1477 while (list_order_it != list_order_end_it) {
1478 cprintf(
"%i OpClass:%i [sn:%lli] ", i, (*list_order_it).queueType,
1479 (*list_order_it).oldestInst);
1489 template <
class Impl>
1493 for (
ThreadID tid = 0; tid < numThreads; ++tid) {
1496 ListIt inst_list_it = instList[tid].begin();
1498 while (inst_list_it != instList[tid].end()) {
1499 cprintf(
"Instruction:%i\n", num);
1500 if (!(*inst_list_it)->isSquashed()) {
1501 if (!(*inst_list_it)->isIssued()) {
1503 cprintf(
"Count:%i\n", valid_num);
1504 }
else if ((*inst_list_it)->isMemRef() &&
1505 !(*inst_list_it)->memOpDone()) {
1509 cprintf(
"Count:%i\n", valid_num);
1513 cprintf(
"PC: %s\n[sn:%lli]\n[tid:%i]\n"
1514 "Issued:%i\nSquashed:%i\n",
1515 (*inst_list_it)->pcState(),
1516 (*inst_list_it)->seqNum,
1517 (*inst_list_it)->threadNumber,
1518 (*inst_list_it)->isIssued(),
1519 (*inst_list_it)->isSquashed());
1521 if ((*inst_list_it)->isMemRef()) {
1522 cprintf(
"MemOpDone:%i\n", (*inst_list_it)->memOpDone());
1532 cprintf(
"Insts to Execute list:\n");
1536 ListIt inst_list_it = instsToExecute.begin();
1538 while (inst_list_it != instsToExecute.end())
1542 if (!(*inst_list_it)->isSquashed()) {
1543 if (!(*inst_list_it)->isIssued()) {
1545 cprintf(
"Count:%i\n", valid_num);
1546 }
else if ((*inst_list_it)->isMemRef() &&
1547 !(*inst_list_it)->memOpDone()) {
1551 cprintf(
"Count:%i\n", valid_num);
1555 cprintf(
"PC: %s\n[sn:%lli]\n[tid:%i]\n"
1556 "Issued:%i\nSquashed:%i\n",
1557 (*inst_list_it)->pcState(),
1558 (*inst_list_it)->seqNum,
1559 (*inst_list_it)->threadNumber,
1560 (*inst_list_it)->isIssued(),
1561 (*inst_list_it)->isSquashed());
1563 if ((*inst_list_it)->isMemRef()) {
1564 cprintf(
"MemOpDone:%i\n", (*inst_list_it)->memOpDone());
1574 #endif//__CPU_O3_INST_QUEUE_IMPL_HH__
void regStats()
Registers statistics.
const FlagsType pdf
Print the percent of the total that this entry represents.
decltype(nullptr) constexpr NoFault
Cycles is a wrapper class for representing cycle counts, i.e.
void doSquash(ThreadID tid)
Does the actual squashing.
void scheduleReadyInsts()
Schedules ready instructions, adding the ready ones (oldest first) to the queue to execute...
const std::string & name()
void violation(DynInstPtr &store, DynInstPtr &faulting_load)
Indicates an ordering violation between a store and a load.
InstructionQueue(O3CPU *cpu_ptr, IEW *iew_ptr, DerivO3CPUParams *params)
Constructs an IQ.
void dumpInsts()
Debugging function to dump out all instructions that are in the IQ.
int wakeDependents(DynInstPtr &completed_inst)
Wakes all dependents of a completed instruction.
void insertNonSpec(DynInstPtr &new_inst)
Inserts a new, non-speculative instruction into the IQ.
Impl::DynInstPtr DynInstPtr
void scheduleNonSpec(const InstSeqNum &inst)
Schedules a single specific non-speculative instruction.
DynInstPtr getInstToExecute()
Returns the oldest scheduled instruction, and removes it from the list of instructions waiting to exe...
FU completion event class.
void insertBarrier(DynInstPtr &barr_inst)
Inserts a memory or write barrier into the IQ to make sure loads and stores are ordered properly...
void addToOrderList(OpClass op_class)
Add an op class to the age order list.
void setActiveThreads(std::list< ThreadID > *at_ptr)
Sets active threads list.
void setIQ(InstructionQueue< Impl > *iq_ptr)
Sets the pointer to the IQ.
unsigned numEntries
The number of entries in the instruction queue.
static constexpr auto NoCapableFU
virtual const char * description() const
Return a C string describing the event.
void setTimeBuffer(TimeBuffer< TimeStruct > *tb_ptr)
Sets the global time buffer.
std::vector< bool > regScoreboard
A cache of the recently woken registers.
void processFUCompletion(DynInstPtr &inst, int fu_idx)
Process FU completion event.
bool isFull()
Returns whether or not the IQ is full.
unsigned numFreeEntries()
Returns total number of free entries.
Tick curTick()
The current simulated tick.
bool hasReadyInsts()
Returns if there are any ready instructions in the IQ.
void blockMemInst(DynInstPtr &blocked_inst)
Defers a memory instruction when it is cache blocked.
void addIfReady(DynInstPtr &inst)
Moves an instruction to the ready queue if it is ready.
void completeMemInst(DynInstPtr &completed_inst)
Completes a memory operation.
IEW * iewStage
Pointer to IEW stage.
void addToProducers(DynInstPtr &new_inst)
Adds an instruction to the dependency graph, as a producer.
void commit(const InstSeqNum &inst, ThreadID tid=0)
Commits all instructions up to and including the given sequence number, for a specific thread...
void addReadyMemInst(DynInstPtr &ready_inst)
Adds a ready memory instruction to the ready list.
void takeOverFrom()
Takes over execution from another CPU's thread.
Cycles commitToIEWDelay
Delay between commit stage and the IQ.
std::string name() const
Returns the name of the IQ.
std::list< ListOrderEntry >::iterator ListOrderIt
const FlagsType total
Print the total.
DynInstPtr getBlockedMemInstToExecute()
Gets a memory instruction that was blocked on the cache.
void resetState()
Resets all instruction queue state.
~InstructionQueue()
Destructs the IQ.
DynInstPtr getDeferredMemInstToExecute()
Gets a memory instruction that was referred due to a delayed DTB translation if it is now ready to ex...
int16_t ThreadID
Thread index/ID type.
void deferMemInst(DynInstPtr &deferred_inst)
Defers a memory instruction when its DTB translation incurs a hw page table walk. ...
void squash(ThreadID tid)
Squashes instructions for a thread.
void init(DerivO3CPUParams *params, ThreadID tid)
Initializes the unit with parameters and a thread id.
DependencyGraph< DynInstPtr > dependGraph
int countInsts()
Debugging function to count how many entries are in the IQ.
void resetEntries()
Resets max entries for all threads.
static const OpClass Num_OpClasses
std::map< InstSeqNum, DynInstPtr >::iterator NonSpecMapIt
int entryAmount(ThreadID num_threads)
Number of entries needed for given amount of threads.
void rescheduleMemInst(DynInstPtr &resched_inst)
Reschedules a memory instruction.
O3CPU * cpu
Pointer to the CPU.
void drainSanityCheck() const
Perform sanity checks after a drain.
Entry for the list age ordering by op class.
std::list< DynInstPtr >::iterator ListIt
unsigned maxEntries[Impl::MaxThreads]
Max IQ Entries Per Thread.
void setIssueToExecuteQueue(TimeBuffer< IssueStruct > *i2eQueue)
Sets the timer buffer between issue and execute.
void cacheUnblocked()
Notify instruction queue that a previous blockage has resolved.
void moveToYoungerInst(ListOrderIt age_order_it)
Called when the oldest instruction has been removed from a ready queue; this places that ready queue ...
unsigned numPhysRegs
The number of physical registers in the CPU.
MemDepUnit memDepUnit[Impl::MaxThreads]
The memory dependence unit, which tracks/predicts memory dependences between instructions.
bool addToDependents(DynInstPtr &new_inst)
Adds an instruction to the dependency graph, as a consumer.
void insert(DynInstPtr &new_inst)
Inserts a new instruction into the IQ.
FUPool * fuPool
Function unit pool.
FUCompletion(DynInstPtr &_inst, int fu_idx, InstructionQueue< Impl > *iq_ptr)
Construct a FU completion event.
bool isDrained() const
Determine if we are drained.
IQPolicy iqPolicy
IQ sharing policy for SMT.
const FlagsType dist
Print the distribution.
A standard instruction queue class.
unsigned totalWidth
The total number of instructions that can be issued in one cycle.
void dumpLists()
Debugging function to dump all the list sizes, as well as print out the list of nonspeculative instru...
void replayMemInst(DynInstPtr &replay_inst)
Replays a memory instruction.
ThreadID numThreads
Number of Total Threads.
void cprintf(const char *format, const Args &...args)
static constexpr auto NoFreeFU