44 #ifndef __CPU_O3_ROB_IMPL_HH__
45 #define __CPU_O3_ROB_IMPL_HH__
50 #include "debug/Fetch.hh"
51 #include "debug/ROB.hh"
52 #include "params/DerivO3CPU.hh"
59 numEntries(params->numROBEntries),
60 squashWidth(params->squashWidth),
62 numThreads(params->numThreads)
64 std::string policy = params->smtROBPolicy;
67 std::transform(policy.begin(), policy.end(), policy.begin(),
68 (int(*)(int)) tolower);
71 if (policy ==
"dynamic") {
79 }
else if (policy ==
"partitioned") {
81 DPRINTF(Fetch,
"ROB sharing policy set to Partitioned\n");
91 }
else if (policy ==
"threshold") {
93 DPRINTF(Fetch,
"ROB sharing policy set to Threshold\n");
95 int threshold = params->smtROBThreshold;;
102 assert(0 &&
"Invalid ROB Sharing Policy.Options Are:{Dynamic,"
103 "Partitioned, Threshold}");
109 template <
class Impl>
113 for (
ThreadID tid = 0; tid < numThreads; tid++) {
114 doneSquashing[tid] =
true;
115 threadEntries[tid] = 0;
116 squashIt[tid] = instList[tid].end();
117 squashedSeqNum[tid] = 0;
123 head = instList[0].end();
124 tail = instList[0].end();
127 template <
class Impl>
131 return cpu->name() +
".rob";
134 template <
class Impl>
138 DPRINTF(
ROB,
"Setting active threads list pointer.\n");
139 activeThreads = at_ptr;
142 template <
class Impl>
146 for (
ThreadID tid = 0; tid < numThreads; tid++)
147 assert(instList[tid].empty());
151 template <
class Impl>
158 template <
class Impl>
162 if (robPolicy != Dynamic || numThreads > 1) {
163 int active_threads = activeThreads->size();
168 while (threads != end) {
171 if (robPolicy == Partitioned) {
172 maxEntries[tid] = numEntries / active_threads;
173 }
else if (robPolicy == Threshold && active_threads == 1) {
174 maxEntries[tid] = numEntries;
180 template <
class Impl>
184 if (robPolicy == Partitioned) {
185 return numEntries / num_threads;
191 template <
class Impl>
197 for (
ThreadID tid = 0; tid < numThreads; tid++)
198 total += countInsts(tid);
203 template <
class Impl>
207 return instList[tid].size();
210 template <
class Impl>
218 DPRINTF(
ROB,
"Adding inst PC %s to the ROB.\n", inst->pcState());
220 assert(numInstsInROB != numEntries);
224 instList[tid].push_back(inst);
227 if (numInstsInROB == 0) {
228 head = instList[tid].begin();
229 assert((*head) == inst);
234 tail = instList[tid].end();
240 ++threadEntries[tid];
242 assert((*tail) == inst);
244 DPRINTF(
ROB,
"[tid:%i] Now has %d instructions.\n", tid, threadEntries[tid]);
247 template <
class Impl>
253 assert(numInstsInROB > 0);
256 InstIt head_it = instList[tid].begin();
260 assert(head_inst->readyToCommit());
262 DPRINTF(
ROB,
"[tid:%u]: Retiring head instruction, "
263 "instruction PC %s, [sn:%lli]\n", tid, head_inst->pcState(),
267 --threadEntries[tid];
269 head_inst->clearInROB();
270 head_inst->setCommitted();
272 instList[tid].erase(head_it);
280 cpu->removeFrontInst(head_inst);
283 template <
class Impl>
288 if (threadEntries[tid] != 0) {
289 return instList[tid].front()->readyToCommit();
295 template <
class Impl>
303 while (threads != end) {
306 if (isHeadReady(tid)) {
314 template <
class Impl>
318 return numEntries - numInstsInROB;
321 template <
class Impl>
325 return maxEntries[tid] - threadEntries[tid];
328 template <
class Impl>
333 DPRINTF(
ROB,
"[tid:%u]: Squashing instructions until [sn:%i].\n",
334 tid, squashedSeqNum[tid]);
336 assert(squashIt[tid] != instList[tid].end());
338 if ((*squashIt[tid])->seqNum < squashedSeqNum[tid]) {
339 DPRINTF(
ROB,
"[tid:%u]: Done squashing instructions.\n",
342 squashIt[tid] = instList[tid].end();
344 doneSquashing[tid] =
true;
348 bool robTailUpdate =
false;
350 for (
int numSquashed = 0;
351 numSquashed < squashWidth &&
352 squashIt[tid] != instList[tid].end() &&
353 (*squashIt[tid])->seqNum > squashedSeqNum[tid];
356 DPRINTF(
ROB,
"[tid:%u]: Squashing instruction PC %s, seq num %i.\n",
357 (*squashIt[tid])->threadNumber,
358 (*squashIt[tid])->pcState(),
359 (*squashIt[tid])->seqNum);
363 (*squashIt[tid])->setSquashed();
365 (*squashIt[tid])->setCanCommit();
368 if (squashIt[tid] == instList[tid].begin()) {
369 DPRINTF(
ROB,
"Reached head of instruction list while "
372 squashIt[tid] = instList[tid].end();
374 doneSquashing[tid] =
true;
379 InstIt tail_thread = instList[tid].end();
382 if ((*squashIt[tid]) == (*tail_thread))
383 robTailUpdate =
true;
390 if ((*squashIt[tid])->seqNum <= squashedSeqNum[tid]) {
391 DPRINTF(
ROB,
"[tid:%u]: Done squashing instructions.\n",
394 squashIt[tid] = instList[tid].end();
396 doneSquashing[tid] =
true;
405 template <
class Impl>
410 bool first_valid =
true;
416 while (threads != end) {
419 if (instList[tid].empty())
423 head = instList[tid].begin();
424 lowest_num = (*head)->seqNum;
429 InstIt head_thread = instList[tid].begin();
433 assert(head_inst != 0);
435 if (head_inst->seqNum < lowest_num) {
437 lowest_num = head_inst->seqNum;
442 head = instList[0].end();
447 template <
class Impl>
451 tail = instList[0].end();
452 bool first_valid =
true;
457 while (threads != end) {
460 if (instList[tid].empty()) {
467 tail = instList[tid].end();
475 InstIt tail_thread = instList[tid].end();
478 if ((*tail_thread)->seqNum > (*tail)->seqNum) {
485 template <
class Impl>
490 DPRINTF(
ROB,
"Does not need to squash due to being empty "
497 DPRINTF(
ROB,
"Starting to squash within the ROB.\n");
499 robStatus[tid] = ROBSquashing;
501 doneSquashing[tid] =
false;
503 squashedSeqNum[tid] = squash_num;
505 if (!instList[tid].empty()) {
506 InstIt tail_thread = instList[tid].end();
509 squashIt[tid] = tail_thread;
515 template <
class Impl>
516 typename Impl::DynInstPtr
519 if (threadEntries[tid] != 0) {
520 InstIt head_thread = instList[tid].begin();
522 assert((*head_thread)->isInROB());
530 template <
class Impl>
531 typename Impl::DynInstPtr
534 InstIt tail_thread = instList[tid].end();
540 template <
class Impl>
544 using namespace Stats;
546 .name(
name() +
".rob_reads")
547 .desc(
"The number of ROB reads");
550 .name(
name() +
".rob_writes")
551 .desc(
"The number of ROB writes");
554 template <
class Impl>
555 typename Impl::DynInstPtr
558 for (
InstIt it = instList[tid].begin(); it != instList[tid].end(); it++) {
559 if ((*it)->seqNum == squash_inst) {
566 #endif//__CPU_O3_ROB_IMPL_HH__
void takeOverFrom()
Takes over another CPU's thread.
bool canCommit()
Is there any commitable head instruction across all threads ready.
void doSquash(ThreadID tid)
Executes the squash, marking squashed instructions.
void retireHead(ThreadID tid)
Retires the head instruction, removing it from the ROB.
const std::string & name()
void resetState()
Reset the ROB state.
void insertInst(DynInstPtr &inst)
Function to insert an instruction into the ROB.
ROB(O3CPU *_cpu, DerivO3CPUParams *params)
ROB constructor.
ThreadID numThreads
Number of active threads.
DynInstPtr findInst(ThreadID tid, InstSeqNum squash_inst)
Returns a pointer to the instruction with the given sequence if it is in the ROB. ...
void updateHead()
Updates the head instruction with the new oldest instruction.
DynInstPtr readTailInst(ThreadID tid)
Returns pointer to the tail instruction within the ROB.
Impl::DynInstPtr DynInstPtr
std::list< DynInstPtr >::iterator InstIt
unsigned numFreeEntries()
Returns the number of total free entries in the ROB.
ROBPolicy robPolicy
ROB resource sharing policy for SMT mode.
void setActiveThreads(std::list< ThreadID > *at_ptr)
Sets pointer to the list of active threads.
void drainSanityCheck() const
Perform sanity checks after a drain.
void updateTail()
Updates the tail instruction with the new youngest instruction.
const FlagsType total
Print the total.
void squash(InstSeqNum squash_num, ThreadID tid)
Squashes all instructions younger than the given sequence number for the specific thread...
int16_t ThreadID
Thread index/ID type.
void regStats()
Registers statistics.
void resetEntries()
Re-adjust ROB partitioning.
bool isHeadReady(ThreadID tid)
Is the oldest instruction across all threads ready.
int countInsts()
This is more of a debugging function than anything.
DynInstPtr readHeadInst(ThreadID tid)
Returns pointer to the head instruction within the ROB.
unsigned numEntries
Number of instructions in the ROB.
int entryAmount(ThreadID num_threads)
Number of entries needed For 'num_threads' amount of threads.
unsigned maxEntries[Impl::MaxThreads]
Max Insts a Thread Can Have in the ROB.