inst_queue_impl.hh (12833:4566a9331697) inst_queue_impl.hh (13429:a1e199fd8122)
1/*
2 * Copyright (c) 2011-2014 ARM Limited
3 * Copyright (c) 2013 Advanced Micro Devices, Inc.
4 * All rights reserved.
5 *
6 * The license below extends only to copyright in the software and shall
7 * not be construed as granting a license to any other intellectual
8 * property including but not limited to intellectual property relating

--- 46 unchanged lines hidden (view full) ---

55#include "params/DerivO3CPU.hh"
56#include "sim/core.hh"
57
58// clang complains about std::set being overloaded with Packet::set if
59// we open up the entire namespace std
60using std::list;
61
62template <class Impl>
1/*
2 * Copyright (c) 2011-2014 ARM Limited
3 * Copyright (c) 2013 Advanced Micro Devices, Inc.
4 * All rights reserved.
5 *
6 * The license below extends only to copyright in the software and shall
7 * not be construed as granting a license to any other intellectual
8 * property including but not limited to intellectual property relating

--- 46 unchanged lines hidden (view full) ---

55#include "params/DerivO3CPU.hh"
56#include "sim/core.hh"
57
58// clang complains about std::set being overloaded with Packet::set if
59// we open up the entire namespace std
60using std::list;
61
62template <class Impl>
63InstructionQueue::FUCompletion::FUCompletion(DynInstPtr &_inst,
63InstructionQueue<Impl>::FUCompletion::FUCompletion(const DynInstPtr &_inst,
64 int fu_idx, InstructionQueue<Impl> *iq_ptr)
65 : Event(Stat_Event_Pri, AutoDelete),
66 inst(_inst), fuIdx(fu_idx), iqPtr(iq_ptr), freeFU(false)
67{
68}
69
70template <class Impl>
71void

--- 508 unchanged lines hidden (view full) ---

580 }
581 }
582
583 return false;
584}
585
586template <class Impl>
587void
64 int fu_idx, InstructionQueue<Impl> *iq_ptr)
65 : Event(Stat_Event_Pri, AutoDelete),
66 inst(_inst), fuIdx(fu_idx), iqPtr(iq_ptr), freeFU(false)
67{
68}
69
70template <class Impl>
71void

--- 508 unchanged lines hidden (view full) ---

580 }
581 }
582
583 return false;
584}
585
586template <class Impl>
587void
588InstructionQueue::insert(DynInstPtr &new_inst)
588InstructionQueue<Impl>::insert(const DynInstPtr &new_inst)
589{
590 if (new_inst->isFloating()) {
591 fpInstQueueWrites++;
592 } else if (new_inst->isVector()) {
593 vecInstQueueWrites++;
594 } else {
595 intInstQueueWrites++;
596 }

--- 29 unchanged lines hidden (view full) ---

626
627 count[new_inst->threadNumber]++;
628
629 assert(freeEntries == (numEntries - countInsts()));
630}
631
632template <class Impl>
633void
589{
590 if (new_inst->isFloating()) {
591 fpInstQueueWrites++;
592 } else if (new_inst->isVector()) {
593 vecInstQueueWrites++;
594 } else {
595 intInstQueueWrites++;
596 }

--- 29 unchanged lines hidden (view full) ---

626
627 count[new_inst->threadNumber]++;
628
629 assert(freeEntries == (numEntries - countInsts()));
630}
631
632template <class Impl>
633void
634InstructionQueue::insertNonSpec(DynInstPtr &new_inst)
634InstructionQueue<Impl>::insertNonSpec(const DynInstPtr &new_inst)
635{
636 // @todo: Clean up this code; can do it by setting inst as unable
637 // to issue, then calling normal insert on the inst.
638 if (new_inst->isFloating()) {
639 fpInstQueueWrites++;
640 } else if (new_inst->isVector()) {
641 vecInstQueueWrites++;
642 } else {

--- 30 unchanged lines hidden (view full) ---

673
674 count[new_inst->threadNumber]++;
675
676 assert(freeEntries == (numEntries - countInsts()));
677}
678
679template <class Impl>
680void
635{
636 // @todo: Clean up this code; can do it by setting inst as unable
637 // to issue, then calling normal insert on the inst.
638 if (new_inst->isFloating()) {
639 fpInstQueueWrites++;
640 } else if (new_inst->isVector()) {
641 vecInstQueueWrites++;
642 } else {

--- 30 unchanged lines hidden (view full) ---

673
674 count[new_inst->threadNumber]++;
675
676 assert(freeEntries == (numEntries - countInsts()));
677}
678
679template <class Impl>
680void
681InstructionQueue::insertBarrier(DynInstPtr &barr_inst)
681InstructionQueue<Impl>::insertBarrier(const DynInstPtr &barr_inst)
682{
683 memDepUnit[barr_inst->threadNumber].insertBarrier(barr_inst);
684
685 insertNonSpec(barr_inst);
686}
687
688template <class Impl>
689typename Impl::DynInstPtr
690InstructionQueue<Impl>::getInstToExecute()
691{
692 assert(!instsToExecute.empty());
682{
683 memDepUnit[barr_inst->threadNumber].insertBarrier(barr_inst);
684
685 insertNonSpec(barr_inst);
686}
687
688template <class Impl>
689typename Impl::DynInstPtr
690InstructionQueue<Impl>::getInstToExecute()
691{
692 assert(!instsToExecute.empty());
693 DynInstPtr inst = instsToExecute.front();
693 DynInstPtr inst = std::move(instsToExecute.front());
694 instsToExecute.pop_front();
695 if (inst->isFloating()) {
696 fpInstQueueReads++;
697 } else if (inst->isVector()) {
698 vecInstQueueReads++;
699 } else {
700 intInstQueueReads++;
701 }

--- 50 unchanged lines hidden (view full) ---

752 ++next_it;
753 }
754
755 readyIt[op_class] = listOrder.insert(next_it, queue_entry);
756}
757
758template <class Impl>
759void
694 instsToExecute.pop_front();
695 if (inst->isFloating()) {
696 fpInstQueueReads++;
697 } else if (inst->isVector()) {
698 vecInstQueueReads++;
699 } else {
700 intInstQueueReads++;
701 }

--- 50 unchanged lines hidden (view full) ---

752 ++next_it;
753 }
754
755 readyIt[op_class] = listOrder.insert(next_it, queue_entry);
756}
757
758template <class Impl>
759void
760InstructionQueue::processFUCompletion(DynInstPtr &inst, int fu_idx)
760InstructionQueue<Impl>::processFUCompletion(const DynInstPtr &inst, int fu_idx)
761{
762 DPRINTF(IQ, "Processing FU completion [sn:%lli]\n", inst->seqNum);
763 assert(!cpu->switchedOut());
764 // The CPU could have been sleeping until this op completed (*extremely*
765 // long latency op). Wake it if it was. This may be overkill.
766 --wbOutstanding;
767 iewStage->wakeCPU();
768

--- 15 unchanged lines hidden (view full) ---

784InstructionQueue<Impl>::scheduleReadyInsts()
785{
786 DPRINTF(IQ, "Attempting to schedule ready instructions from "
787 "the IQ.\n");
788
789 IssueStruct *i2e_info = issueToExecuteQueue->access(0);
790
791 DynInstPtr mem_inst;
761{
762 DPRINTF(IQ, "Processing FU completion [sn:%lli]\n", inst->seqNum);
763 assert(!cpu->switchedOut());
764 // The CPU could have been sleeping until this op completed (*extremely*
765 // long latency op). Wake it if it was. This may be overkill.
766 --wbOutstanding;
767 iewStage->wakeCPU();
768

--- 15 unchanged lines hidden (view full) ---

784InstructionQueue<Impl>::scheduleReadyInsts()
785{
786 DPRINTF(IQ, "Attempting to schedule ready instructions from "
787 "the IQ.\n");
788
789 IssueStruct *i2e_info = issueToExecuteQueue->access(0);
790
791 DynInstPtr mem_inst;
792 while (mem_inst = getDeferredMemInstToExecute()) {
792 while (mem_inst = std::move(getDeferredMemInstToExecute())) {
793 addReadyMemInst(mem_inst);
794 }
795
796 // See if any cache blocked instructions are able to be executed
793 addReadyMemInst(mem_inst);
794 }
795
796 // See if any cache blocked instructions are able to be executed
797 while (mem_inst = getBlockedMemInstToExecute()) {
797 while (mem_inst = std::move(getBlockedMemInstToExecute())) {
798 addReadyMemInst(mem_inst);
799 }
800
801 // Have iterator to head of the list
802 // While I haven't exceeded bandwidth or reached the end of the list,
803 // Try to get a FU that can do what this op needs.
804 // If successful, change the oldestInst to the new top of the list, put
805 // the queue in the proper place in the list.

--- 184 unchanged lines hidden (view full) ---

990 instList[tid].pop_front();
991 }
992
993 assert(freeEntries == (numEntries - countInsts()));
994}
995
996template <class Impl>
997int
798 addReadyMemInst(mem_inst);
799 }
800
801 // Have iterator to head of the list
802 // While I haven't exceeded bandwidth or reached the end of the list,
803 // Try to get a FU that can do what this op needs.
804 // If successful, change the oldestInst to the new top of the list, put
805 // the queue in the proper place in the list.

--- 184 unchanged lines hidden (view full) ---

990 instList[tid].pop_front();
991 }
992
993 assert(freeEntries == (numEntries - countInsts()));
994}
995
996template <class Impl>
997int
998InstructionQueue::wakeDependents(DynInstPtr &completed_inst)
998InstructionQueue<Impl>::wakeDependents(const DynInstPtr &completed_inst)
999{
1000 int dependents = 0;
1001
1002 // The instruction queue here takes care of both floating and int ops
1003 if (completed_inst->isFloating()) {
1004 fpInstQueueWakeupAccesses++;
1005 } else if (completed_inst->isVector()) {
1006 vecInstQueueWakeupAccesses++;

--- 67 unchanged lines hidden (view full) ---

1074 // Mark the scoreboard as having that register ready.
1075 regScoreboard[dest_reg->flatIndex()] = true;
1076 }
1077 return dependents;
1078}
1079
1080template <class Impl>
1081void
999{
1000 int dependents = 0;
1001
1002 // The instruction queue here takes care of both floating and int ops
1003 if (completed_inst->isFloating()) {
1004 fpInstQueueWakeupAccesses++;
1005 } else if (completed_inst->isVector()) {
1006 vecInstQueueWakeupAccesses++;

--- 67 unchanged lines hidden (view full) ---

1074 // Mark the scoreboard as having that register ready.
1075 regScoreboard[dest_reg->flatIndex()] = true;
1076 }
1077 return dependents;
1078}
1079
1080template <class Impl>
1081void
1082InstructionQueue::addReadyMemInst(DynInstPtr &ready_inst)
1082InstructionQueue<Impl>::addReadyMemInst(const DynInstPtr &ready_inst)
1083{
1084 OpClass op_class = ready_inst->opClass();
1085
1086 readyInsts[op_class].push(ready_inst);
1087
1088 // Will need to reorder the list if either a queue is not on the list,
1089 // or it has an older instruction than last time.
1090 if (!queueOnList[op_class]) {

--- 6 unchanged lines hidden (view full) ---

1097
1098 DPRINTF(IQ, "Instruction is ready to issue, putting it onto "
1099 "the ready list, PC %s opclass:%i [sn:%lli].\n",
1100 ready_inst->pcState(), op_class, ready_inst->seqNum);
1101}
1102
1103template <class Impl>
1104void
1083{
1084 OpClass op_class = ready_inst->opClass();
1085
1086 readyInsts[op_class].push(ready_inst);
1087
1088 // Will need to reorder the list if either a queue is not on the list,
1089 // or it has an older instruction than last time.
1090 if (!queueOnList[op_class]) {

--- 6 unchanged lines hidden (view full) ---

1097
1098 DPRINTF(IQ, "Instruction is ready to issue, putting it onto "
1099 "the ready list, PC %s opclass:%i [sn:%lli].\n",
1100 ready_inst->pcState(), op_class, ready_inst->seqNum);
1101}
1102
1103template <class Impl>
1104void
1105InstructionQueue::rescheduleMemInst(DynInstPtr &resched_inst)
1105InstructionQueue<Impl>::rescheduleMemInst(const DynInstPtr &resched_inst)
1106{
1107 DPRINTF(IQ, "Rescheduling mem inst [sn:%lli]\n", resched_inst->seqNum);
1108
1109 // Reset DTB translation state
1110 resched_inst->translationStarted(false);
1111 resched_inst->translationCompleted(false);
1112
1113 resched_inst->clearCanIssue();
1114 memDepUnit[resched_inst->threadNumber].reschedule(resched_inst);
1115}
1116
1117template <class Impl>
1118void
1106{
1107 DPRINTF(IQ, "Rescheduling mem inst [sn:%lli]\n", resched_inst->seqNum);
1108
1109 // Reset DTB translation state
1110 resched_inst->translationStarted(false);
1111 resched_inst->translationCompleted(false);
1112
1113 resched_inst->clearCanIssue();
1114 memDepUnit[resched_inst->threadNumber].reschedule(resched_inst);
1115}
1116
1117template <class Impl>
1118void
1119InstructionQueue::replayMemInst(DynInstPtr &replay_inst)
1119InstructionQueue<Impl>::replayMemInst(const DynInstPtr &replay_inst)
1120{
1121 memDepUnit[replay_inst->threadNumber].replay();
1122}
1123
1124template <class Impl>
1125void
1120{
1121 memDepUnit[replay_inst->threadNumber].replay();
1122}
1123
1124template <class Impl>
1125void
1126InstructionQueue::completeMemInst(DynInstPtr &completed_inst)
1126InstructionQueue<Impl>::completeMemInst(const DynInstPtr &completed_inst)
1127{
1128 ThreadID tid = completed_inst->threadNumber;
1129
1130 DPRINTF(IQ, "Completing mem instruction PC: %s [sn:%lli]\n",
1131 completed_inst->pcState(), completed_inst->seqNum);
1132
1133 ++freeEntries;
1134
1135 completed_inst->memOpDone(true);
1136
1137 memDepUnit[tid].completed(completed_inst);
1138 count[tid]--;
1139}
1140
1141template <class Impl>
1142void
1127{
1128 ThreadID tid = completed_inst->threadNumber;
1129
1130 DPRINTF(IQ, "Completing mem instruction PC: %s [sn:%lli]\n",
1131 completed_inst->pcState(), completed_inst->seqNum);
1132
1133 ++freeEntries;
1134
1135 completed_inst->memOpDone(true);
1136
1137 memDepUnit[tid].completed(completed_inst);
1138 count[tid]--;
1139}
1140
1141template <class Impl>
1142void
1143InstructionQueue::deferMemInst(DynInstPtr &deferred_inst)
1143InstructionQueue<Impl>::deferMemInst(const DynInstPtr &deferred_inst)
1144{
1145 deferredMemInsts.push_back(deferred_inst);
1146}
1147
1148template <class Impl>
1149void
1144{
1145 deferredMemInsts.push_back(deferred_inst);
1146}
1147
1148template <class Impl>
1149void
1150InstructionQueue::blockMemInst(DynInstPtr &blocked_inst)
1150InstructionQueue<Impl>::blockMemInst(const DynInstPtr &blocked_inst)
1151{
1152 blocked_inst->translationStarted(false);
1153 blocked_inst->translationCompleted(false);
1154
1155 blocked_inst->clearIssued();
1156 blocked_inst->clearCanIssue();
1157 blockedMemInsts.push_back(blocked_inst);
1158}

--- 9 unchanged lines hidden (view full) ---

1168
1169template <class Impl>
1170typename Impl::DynInstPtr
1171InstructionQueue<Impl>::getDeferredMemInstToExecute()
1172{
1173 for (ListIt it = deferredMemInsts.begin(); it != deferredMemInsts.end();
1174 ++it) {
1175 if ((*it)->translationCompleted() || (*it)->isSquashed()) {
1151{
1152 blocked_inst->translationStarted(false);
1153 blocked_inst->translationCompleted(false);
1154
1155 blocked_inst->clearIssued();
1156 blocked_inst->clearCanIssue();
1157 blockedMemInsts.push_back(blocked_inst);
1158}

--- 9 unchanged lines hidden (view full) ---

1168
1169template <class Impl>
1170typename Impl::DynInstPtr
1171InstructionQueue<Impl>::getDeferredMemInstToExecute()
1172{
1173 for (ListIt it = deferredMemInsts.begin(); it != deferredMemInsts.end();
1174 ++it) {
1175 if ((*it)->translationCompleted() || (*it)->isSquashed()) {
1176 DynInstPtr mem_inst = *it;
1176 DynInstPtr mem_inst = std::move(*it);
1177 deferredMemInsts.erase(it);
1178 return mem_inst;
1179 }
1180 }
1181 return nullptr;
1182}
1183
1184template <class Impl>
1185typename Impl::DynInstPtr
1186InstructionQueue<Impl>::getBlockedMemInstToExecute()
1187{
1188 if (retryMemInsts.empty()) {
1189 return nullptr;
1190 } else {
1177 deferredMemInsts.erase(it);
1178 return mem_inst;
1179 }
1180 }
1181 return nullptr;
1182}
1183
1184template <class Impl>
1185typename Impl::DynInstPtr
1186InstructionQueue<Impl>::getBlockedMemInstToExecute()
1187{
1188 if (retryMemInsts.empty()) {
1189 return nullptr;
1190 } else {
1191 DynInstPtr mem_inst = retryMemInsts.front();
1191 DynInstPtr mem_inst = std::move(retryMemInsts.front());
1192 retryMemInsts.pop_front();
1193 return mem_inst;
1194 }
1195}
1196
1197template <class Impl>
1198void
1192 retryMemInsts.pop_front();
1193 return mem_inst;
1194 }
1195}
1196
1197template <class Impl>
1198void
1199InstructionQueue::violation(DynInstPtr &store,
1200 DynInstPtr &faulting_load)
1199InstructionQueue<Impl>::violation(const DynInstPtr &store,
1200 const DynInstPtr &faulting_load)
1201{
1202 intInstQueueWrites++;
1203 memDepUnit[store->threadNumber].violation(store, faulting_load);
1204}
1205
1206template <class Impl>
1207void
1208InstructionQueue<Impl>::squash(ThreadID tid)

--- 150 unchanged lines hidden (view full) ---

1359 }
1360 instList[tid].erase(squash_it--);
1361 ++iqSquashedInstsExamined;
1362 }
1363}
1364
1365template <class Impl>
1366bool
1201{
1202 intInstQueueWrites++;
1203 memDepUnit[store->threadNumber].violation(store, faulting_load);
1204}
1205
1206template <class Impl>
1207void
1208InstructionQueue<Impl>::squash(ThreadID tid)

--- 150 unchanged lines hidden (view full) ---

1359 }
1360 instList[tid].erase(squash_it--);
1361 ++iqSquashedInstsExamined;
1362 }
1363}
1364
1365template <class Impl>
1366bool
1367InstructionQueue::addToDependents(DynInstPtr &new_inst)
1367InstructionQueue<Impl>::addToDependents(const DynInstPtr &new_inst)
1368{
1369 // Loop through the instruction's source registers, adding
1370 // them to the dependency list if they are not ready.
1371 int8_t total_src_regs = new_inst->numSrcRegs();
1372 bool return_val = false;
1373
1374 for (int src_reg_idx = 0;
1375 src_reg_idx < total_src_regs;

--- 31 unchanged lines hidden (view full) ---

1407 }
1408 }
1409
1410 return return_val;
1411}
1412
1413template <class Impl>
1414void
1368{
1369 // Loop through the instruction's source registers, adding
1370 // them to the dependency list if they are not ready.
1371 int8_t total_src_regs = new_inst->numSrcRegs();
1372 bool return_val = false;
1373
1374 for (int src_reg_idx = 0;
1375 src_reg_idx < total_src_regs;

--- 31 unchanged lines hidden (view full) ---

1407 }
1408 }
1409
1410 return return_val;
1411}
1412
1413template <class Impl>
1414void
1415InstructionQueue::addToProducers(DynInstPtr &new_inst)
1415InstructionQueue<Impl>::addToProducers(const DynInstPtr &new_inst)
1416{
1417 // Nothing really needs to be marked when an instruction becomes
1418 // the producer of a register's value, but for convenience a ptr
1419 // to the producing instruction will be placed in the head node of
1420 // the dependency links.
1421 int8_t total_dest_regs = new_inst->numDestRegs();
1422
1423 for (int dest_reg_idx = 0;

--- 19 unchanged lines hidden (view full) ---

1443
1444 // Mark the scoreboard to say it's not yet ready.
1445 regScoreboard[dest_reg->flatIndex()] = false;
1446 }
1447}
1448
1449template <class Impl>
1450void
1416{
1417 // Nothing really needs to be marked when an instruction becomes
1418 // the producer of a register's value, but for convenience a ptr
1419 // to the producing instruction will be placed in the head node of
1420 // the dependency links.
1421 int8_t total_dest_regs = new_inst->numDestRegs();
1422
1423 for (int dest_reg_idx = 0;

--- 19 unchanged lines hidden (view full) ---

1443
1444 // Mark the scoreboard to say it's not yet ready.
1445 regScoreboard[dest_reg->flatIndex()] = false;
1446 }
1447}
1448
1449template <class Impl>
1450void
1451InstructionQueue::addIfReady(DynInstPtr &inst)
1451InstructionQueue<Impl>::addIfReady(const DynInstPtr &inst)
1452{
1453 // If the instruction now has all of its source registers
1454 // available, then add it to the list of ready instructions.
1455 if (inst->readyToIssue()) {
1456
1457 //Add the instruction to the proper ready list.
1458 if (inst->isMemRef()) {
1459

--- 194 unchanged lines hidden ---
1452{
1453 // If the instruction now has all of its source registers
1454 // available, then add it to the list of ready instructions.
1455 if (inst->readyToIssue()) {
1456
1457 //Add the instruction to the proper ready list.
1458 if (inst->isMemRef()) {
1459

--- 194 unchanged lines hidden ---