2c2
< * Copyright (c) 2004-2005 The Regents of The University of Michigan
---
> * Copyright (c) 2004-2006 The Regents of The University of Michigan
29,31d28
< #ifndef __CPU_O3_CPU_ROB_IMPL_HH__
< #define __CPU_O3_CPU_ROB_IMPL_HH__
<
34a32,33
> using namespace std;
>
36c35,37
< ROB<Impl>::ROB(unsigned _numEntries, unsigned _squashWidth)
---
> ROB<Impl>::ROB(unsigned _numEntries, unsigned _squashWidth,
> string _smtROBPolicy, unsigned _smtROBThreshold,
> unsigned _numThreads)
40c41,42
< squashedSeqNum(0)
---
> squashedSeqNum(0),
> numThreads(_numThreads)
42c44,89
< doneSquashing = true;
---
> for (int tid=0; tid < numThreads; tid++) {
> doneSquashing[tid] = true;
> threadEntries[tid] = 0;
> }
>
> string policy = _smtROBPolicy;
>
> //Convert string to lowercase
> std::transform(policy.begin(), policy.end(), policy.begin(),
> (int(*)(int)) tolower);
>
> //Figure out rob policy
> if (policy == "dynamic") {
> robPolicy = Dynamic;
>
> //Set Max Entries to Total ROB Capacity
> for (int i = 0; i < numThreads; i++) {
> maxEntries[i]=numEntries;
> }
>
> } else if (policy == "partitioned") {
> robPolicy = Partitioned;
> DPRINTF(Fetch, "ROB sharing policy set to Partitioned\n");
>
> //@todo:make work if part_amt doesnt divide evenly.
> int part_amt = numEntries / numThreads;
>
> //Divide ROB up evenly
> for (int i = 0; i < numThreads; i++) {
> maxEntries[i]=part_amt;
> }
>
> } else if (policy == "threshold") {
> robPolicy = Threshold;
> DPRINTF(Fetch, "ROB sharing policy set to Threshold\n");
>
> int threshold = _smtROBThreshold;;
>
> //Divide up by threshold amount
> for (int i = 0; i < numThreads; i++) {
> maxEntries[i]=threshold;
> }
> } else {
> assert(0 && "Invalid ROB Sharing Policy.Options Are:{Dynamic,"
> "Partitioned, Threshold}");
> }
45a93,99
> std::string
> ROB<Impl>::name() const
> {
> return cpu->name() + ".rob";
> }
>
> template <class Impl>
51,54c105,108
< // Set the tail to the beginning of the CPU instruction list so that
< // upon the first instruction being inserted into the ROB, the tail
< // iterator can simply be incremented.
< tail = cpu->instList.begin();
---
> // Set the per-thread iterators to the end of the instruction list.
> for (int i=0; i < numThreads;i++) {
> squashIt[i] = instList[i].end();
> }
56,57c110,113
< // Set the squash iterator to the end of the instruction list.
< squashIt = cpu->instList.end();
---
> // Initialize the "universal" ROB head & tail point to invalid
> // pointers
> head = instList[0].end();
> tail = instList[0].end();
61,62c117,118
< int
< ROB<Impl>::countInsts()
---
> void
> ROB<Impl>::setActiveThreads(list<unsigned> *at_ptr)
64,66c120,122
< // Start at 1; if the tail matches cpu->instList.begin(), then there is
< // one inst in the ROB.
< int return_val = 1;
---
> DPRINTF(ROB, "Setting active threads list pointer.\n");
> activeThreads = at_ptr;
> }
68,77c124,129
< // There are quite a few special cases. Do not use this function other
< // than for debugging purposes.
< if (cpu->instList.begin() == cpu->instList.end()) {
< // In this case there are no instructions in the list. The ROB
< // must be empty.
< return 0;
< } else if (tail == cpu->instList.end()) {
< // In this case, the tail is not yet pointing to anything valid.
< // The ROB must be empty.
< return 0;
---
> template <class Impl>
> void
> ROB<Impl>::switchOut()
> {
> for (int tid = 0; tid < numThreads; tid++) {
> instList[tid].clear();
78a131
> }
80,85c133,140
< // Iterate through the ROB from the head to the tail, counting the
< // entries.
< for (InstIt_t i = cpu->instList.begin(); i != tail; ++i)
< {
< assert(i != cpu->instList.end());
< ++return_val;
---
> template <class Impl>
> void
> ROB<Impl>::takeOverFrom()
> {
> for (int tid=0; tid < numThreads; tid++) {
> doneSquashing[tid] = true;
> threadEntries[tid] = 0;
> squashIt[tid] = instList[tid].end();
86a142
> numInstsInROB = 0;
88c144,148
< return return_val;
---
> // Initialize the "universal" ROB head & tail point to invalid
> // pointers
> head = instList[0].end();
> tail = instList[0].end();
> }
90,93c150,167
< // Because the head won't be tracked properly until the ROB gets the
< // first instruction, and any time that the ROB is empty and has not
< // yet gotten the instruction, this function doesn't work.
< // return numInstsInROB;
---
> template <class Impl>
> void
> ROB<Impl>::resetEntries()
> {
> if (robPolicy != Dynamic || numThreads > 1) {
> int active_threads = (*activeThreads).size();
>
> list<unsigned>::iterator threads = (*activeThreads).begin();
> list<unsigned>::iterator list_end = (*activeThreads).end();
>
> while (threads != list_end) {
> if (robPolicy == Partitioned) {
> maxEntries[*threads++] = numEntries / active_threads;
> } else if (robPolicy == Threshold && active_threads == 1) {
> maxEntries[*threads++] = numEntries;
> }
> }
> }
96a171,200
> int
> ROB<Impl>::entryAmount(int num_threads)
> {
> if (robPolicy == Partitioned) {
> return numEntries / num_threads;
> } else {
> return 0;
> }
> }
>
> template <class Impl>
> int
> ROB<Impl>::countInsts()
> {
> int total=0;
>
> for (int i=0;i < numThreads;i++)
> total += countInsts(i);
>
> return total;
> }
>
> template <class Impl>
> int
> ROB<Impl>::countInsts(unsigned tid)
> {
> return instList[tid].size();
> }
>
> template <class Impl>
100,102c204
< // Make sure we have the right number of instructions.
< assert(numInstsInROB == countInsts());
< // Make sure the instruction is valid.
---
> //assert(numInstsInROB == countInsts());
105c207
< DPRINTF(ROB, "ROB: Adding inst PC %#x to the ROB.\n", inst->readPC());
---
> DPRINTF(ROB, "Adding inst PC %#x to the ROB.\n", inst->readPC());
107d208
< // If the ROB is full then exit.
110c211
< ++numInstsInROB;
---
> int tid = inst->threadNumber;
112,119c213,218
< // Increment the tail iterator, moving it one instruction back.
< // There is a special case if the ROB was empty prior to this insertion,
< // in which case the tail will be pointing at instList.end(). If that
< // happens, then reset the tail to the beginning of the list.
< if (tail != cpu->instList.end()) {
< ++tail;
< } else {
< tail = cpu->instList.begin();
---
> instList[tid].push_back(inst);
>
> //Set Up head iterator if this is the 1st instruction in the ROB
> if (numInstsInROB == 0) {
> head = instList[tid].begin();
> assert((*head) == inst);
122,124c221,224
< // Make sure the tail iterator is actually pointing at the instruction
< // added.
< assert((*tail) == inst);
---
> //Must Decrement for iterator to actually be valid since __.end()
> //actually points to 1 after the last inst
> tail = instList[tid].end();
> tail--;
126c226
< DPRINTF(ROB, "ROB: Now has %d instructions.\n", numInstsInROB);
---
> inst->setInROB();
127a228,233
> ++numInstsInROB;
> ++threadEntries[tid];
>
> assert((*tail) == inst);
>
> DPRINTF(ROB, "[tid:%i] Now has %d instructions.\n", tid, threadEntries[tid]);
131a238
> /*
136c243
< assert(numInstsInROB == countInsts());
---
> //assert(numInstsInROB == countInsts());
138a246,262
> int tid = (*head)->threadNumber;
>
> retireHead(tid);
>
> if (numInstsInROB == 0) {
> tail = instList[tid].end();
> }
> }
> */
>
> template <class Impl>
> void
> ROB<Impl>::retireHead(unsigned tid)
> {
> //assert(numInstsInROB == countInsts());
> assert(numInstsInROB > 0);
>
140c264
< DynInstPtr head_inst = cpu->instList.front();
---
> InstIt head_it = instList[tid].begin();
142c266,267
< // Make certain this can retire.
---
> DynInstPtr head_inst = (*head_it);
>
145,146c270,271
< DPRINTF(ROB, "ROB: Retiring head instruction of the ROB, "
< "instruction PC %#x, seq num %i\n", head_inst->readPC(),
---
> DPRINTF(ROB, "[tid:%u]: Retiring head instruction, "
> "instruction PC %#x,[sn:%lli]\n", tid, head_inst->readPC(),
149d273
< // Keep track of how many instructions are in the ROB.
150a275
> --threadEntries[tid];
152,155c277,287
< // Tell CPU to remove the instruction from the list of instructions.
< // A special case is needed if the instruction being retired is the
< // only instruction in the ROB; otherwise the tail iterator will become
< // invalidated.
---
> head_inst->removeInROB();
> head_inst->setCommitted();
>
> instList[tid].erase(head_it);
>
> //Update "Global" Head of ROB
> updateHead();
>
> // @todo: A special case is needed if the instruction being
> // retired is the only instruction in the ROB; otherwise the tail
> // iterator will become invalidated.
156a289,297
> }
> /*
> template <class Impl>
> bool
> ROB<Impl>::isHeadReady()
> {
> if (numInstsInROB != 0) {
> return (*head)->readyToCommit();
> }
158,159c299,307
< if (numInstsInROB == 0) {
< tail = cpu->instList.end();
---
> return false;
> }
> */
> template <class Impl>
> bool
> ROB<Impl>::isHeadReady(unsigned tid)
> {
> if (threadEntries[tid] != 0) {
> return instList[tid].front()->readyToCommit();
160a309,310
>
> return false;
165c315
< ROB<Impl>::isHeadReady()
---
> ROB<Impl>::canCommit()
167,168c317,325
< if (numInstsInROB != 0) {
< return cpu->instList.front()->readyToCommit();
---
> //@todo: set ActiveThreads through ROB or CPU
> list<unsigned>::iterator threads = (*activeThreads).begin();
>
> while (threads != (*activeThreads).end()) {
> unsigned tid = *threads++;
>
> if (isHeadReady(tid)) {
> return true;
> }
178c335
< assert(numInstsInROB == countInsts());
---
> //assert(numInstsInROB == countInsts());
183a341,347
> unsigned
> ROB<Impl>::numFreeEntries(unsigned tid)
> {
> return maxEntries[tid] - threadEntries[tid];
> }
>
> template <class Impl>
185c349
< ROB<Impl>::doSquash()
---
> ROB<Impl>::doSquash(unsigned tid)
187c351,352
< DPRINTF(ROB, "ROB: Squashing instructions.\n");
---
> DPRINTF(ROB, "[tid:%u]: Squashing instructions until [sn:%i].\n",
> tid, squashedSeqNum);
189c354
< assert(squashIt != cpu->instList.end());
---
> assert(squashIt[tid] != instList[tid].end());
190a356,367
> if ((*squashIt[tid])->seqNum < squashedSeqNum) {
> DPRINTF(ROB, "[tid:%u]: Done squashing instructions.\n",
> tid);
>
> squashIt[tid] = instList[tid].end();
>
> doneSquashing[tid] = true;
> return;
> }
>
> bool robTailUpdate = false;
>
192c369,371
< numSquashed < squashWidth && (*squashIt)->seqNum != squashedSeqNum;
---
> numSquashed < squashWidth &&
> squashIt[tid] != instList[tid].end() &&
> (*squashIt[tid])->seqNum > squashedSeqNum;
195,196c374,377
< // Ensure that the instruction is younger.
< assert((*squashIt)->seqNum > squashedSeqNum);
---
> DPRINTF(ROB, "[tid:%u]: Squashing instruction PC %#x, seq num %i.\n",
> (*squashIt[tid])->threadNumber,
> (*squashIt[tid])->readPC(),
> (*squashIt[tid])->seqNum);
198,200d378
< DPRINTF(ROB, "ROB: Squashing instruction PC %#x, seq num %i.\n",
< (*squashIt)->readPC(), (*squashIt)->seqNum);
<
203c381
< (*squashIt)->setSquashed();
---
> (*squashIt[tid])->setSquashed();
205c383
< (*squashIt)->setCanCommit();
---
> (*squashIt[tid])->setCanCommit();
207,215c385,387
< // Special case for when squashing due to a syscall. It's possible
< // that the squash happened after the head instruction was already
< // committed, meaning that (*squashIt)->seqNum != squashedSeqNum
< // will never be false. Normally the squash would never be able
< // to go past the head of the ROB; in this case it might, so it
< // must be handled otherwise it will segfault.
< #if !FULL_SYSTEM
< if (squashIt == cpu->instList.begin()) {
< DPRINTF(ROB, "ROB: Reached head of instruction list while "
---
>
> if (squashIt[tid] == instList[tid].begin()) {
> DPRINTF(ROB, "Reached head of instruction list while "
218c390
< squashIt = cpu->instList.end();
---
> squashIt[tid] = instList[tid].end();
220c392
< doneSquashing = true;
---
> doneSquashing[tid] = true;
224d395
< #endif
226,227c397,403
< // Move the tail iterator to the next instruction.
< squashIt--;
---
> InstIt tail_thread = instList[tid].end();
> tail_thread--;
>
> if ((*squashIt[tid]) == (*tail_thread))
> robTailUpdate = true;
>
> squashIt[tid]--;
232,233c408,410
< if ((*squashIt)->seqNum == squashedSeqNum) {
< DPRINTF(ROB, "ROB: Done squashing instructions.\n");
---
> if ((*squashIt[tid])->seqNum <= squashedSeqNum) {
> DPRINTF(ROB, "[tid:%u]: Done squashing instructions.\n",
> tid);
235c412
< squashIt = cpu->instList.end();
---
> squashIt[tid] = instList[tid].end();
237c414
< doneSquashing = true;
---
> doneSquashing[tid] = true;
238a416,419
>
> if (robTailUpdate) {
> updateTail();
> }
240a422
>
243c425
< ROB<Impl>::squash(InstSeqNum squash_num)
---
> ROB<Impl>::updateHead()
245,246c427,429
< DPRINTF(ROB, "ROB: Starting to squash within the ROB.\n");
< doneSquashing = false;
---
> DynInstPtr head_inst;
> InstSeqNum lowest_num = 0;
> bool first_valid = true;
247a431,519
> // @todo: set ActiveThreads through ROB or CPU
> list<unsigned>::iterator threads = (*activeThreads).begin();
>
> while (threads != (*activeThreads).end()) {
> unsigned thread_num = *threads++;
>
> if (instList[thread_num].empty())
> continue;
>
> if (first_valid) {
> head = instList[thread_num].begin();
> lowest_num = (*head)->seqNum;
> first_valid = false;
> continue;
> }
>
> InstIt head_thread = instList[thread_num].begin();
>
> DynInstPtr head_inst = (*head_thread);
>
> assert(head_inst != 0);
>
> if (head_inst->seqNum < lowest_num) {
> head = head_thread;
> lowest_num = head_inst->seqNum;
> }
> }
>
> if (first_valid) {
> head = instList[0].end();
> }
>
> }
>
> template <class Impl>
> void
> ROB<Impl>::updateTail()
> {
> tail = instList[0].end();
> bool first_valid = true;
>
> list<unsigned>::iterator threads = (*activeThreads).begin();
>
> while (threads != (*activeThreads).end()) {
> unsigned tid = *threads++;
>
> if (instList[tid].empty()) {
> continue;
> }
>
> // If this is the first valid then assign w/out
> // comparison
> if (first_valid) {
> tail = instList[tid].end();
> tail--;
> first_valid = false;
> continue;
> }
>
> // Assign new tail if this thread's tail is younger
> // than our current "tail high"
> InstIt tail_thread = instList[tid].end();
> tail_thread--;
>
> if ((*tail_thread)->seqNum > (*tail)->seqNum) {
> tail = tail_thread;
> }
> }
> }
>
>
> template <class Impl>
> void
> ROB<Impl>::squash(InstSeqNum squash_num,unsigned tid)
> {
> if (isEmpty()) {
> DPRINTF(ROB, "Does not need to squash due to being empty "
> "[sn:%i]\n",
> squash_num);
>
> return;
> }
>
> DPRINTF(ROB, "Starting to squash within the ROB.\n");
>
> robStatus[tid] = ROBSquashing;
>
> doneSquashing[tid] = false;
>
250c522,524
< assert(tail != cpu->instList.end());
---
> if (!instList[tid].empty()) {
> InstIt tail_thread = instList[tid].end();
> tail_thread--;
252c526
< squashIt = tail;
---
> squashIt[tid] = tail_thread;
254c528,529
< doSquash();
---
> doSquash(tid);
> }
255a531,549
> /*
> template <class Impl>
> typename Impl::DynInstPtr
> ROB<Impl>::readHeadInst()
> {
> if (numInstsInROB != 0) {
> assert((*head)->isInROB()==true);
> return *head;
> } else {
> return dummyInst;
> }
> }
> */
> template <class Impl>
> typename Impl::DynInstPtr
> ROB<Impl>::readHeadInst(unsigned tid)
> {
> if (threadEntries[tid] != 0) {
> InstIt head_thread = instList[tid].begin();
256a551,558
> assert((*head_thread)->isInROB()==true);
>
> return *head_thread;
> } else {
> return dummyInst;
> }
> }
> /*
261c563
< assert(numInstsInROB == countInsts());
---
> //assert(numInstsInROB == countInsts());
263c565
< DynInstPtr head_inst = cpu->instList.front();
---
> DynInstPtr head_inst = *head;
269a572,582
> ROB<Impl>::readHeadPC(unsigned tid)
> {
> //assert(numInstsInROB == countInsts());
> InstIt head_thread = instList[tid].begin();
>
> return (*head_thread)->readPC();
> }
>
>
> template <class Impl>
> uint64_t
272c585
< assert(numInstsInROB == countInsts());
---
> //assert(numInstsInROB == countInsts());
274c587
< DynInstPtr head_inst = cpu->instList.front();
---
> DynInstPtr head_inst = *head;
279a593,602
> uint64_t
> ROB<Impl>::readHeadNextPC(unsigned tid)
> {
> //assert(numInstsInROB == countInsts());
> InstIt head_thread = instList[tid].begin();
>
> return (*head_thread)->readNextPC();
> }
>
> template <class Impl>
283,286c606,607
< // Return the last sequence number that has not been squashed. Other
< // stages can use it to squash any instructions younger than the current
< // tail.
< DynInstPtr head_inst = cpu->instList.front();
---
> //assert(numInstsInROB == countInsts());
> DynInstPtr head_inst = *head;
291a613,644
> InstSeqNum
> ROB<Impl>::readHeadSeqNum(unsigned tid)
> {
> InstIt head_thread = instList[tid].begin();
>
> return ((*head_thread)->seqNum);
> }
>
> template <class Impl>
> typename Impl::DynInstPtr
> ROB<Impl>::readTailInst()
> {
> //assert(numInstsInROB == countInsts());
> //assert(tail != instList[0].end());
>
> return (*tail);
> }
> */
> template <class Impl>
> typename Impl::DynInstPtr
> ROB<Impl>::readTailInst(unsigned tid)
> {
> //assert(tail_thread[tid] != instList[tid].end());
>
> InstIt tail_thread = instList[tid].end();
> tail_thread--;
>
> return *tail_thread;
> }
>
> /*
> template <class Impl>
295c648
< assert(numInstsInROB == countInsts());
---
> //assert(numInstsInROB == countInsts());
297c650
< assert(tail != cpu->instList.end());
---
> //assert(tail != instList[0].end());
302a656,667
> uint64_t
> ROB<Impl>::readTailPC(unsigned tid)
> {
> //assert(tail_thread[tid] != instList[tid].end());
>
> InstIt tail_thread = instList[tid].end();
> tail_thread--;
>
> return (*tail_thread)->readPC();
> }
>
> template <class Impl>
312c677,691
< #endif // __CPU_O3_CPU_ROB_IMPL_HH__
---
> template <class Impl>
> InstSeqNum
> ROB<Impl>::readTailSeqNum(unsigned tid)
> {
> // Return the last sequence number that has not been squashed. Other
> // stages can use it to squash any instructions younger than the current
> // tail.
> // assert(tail_thread[tid] != instList[tid].end());
>
> InstIt tail_thread = instList[tid].end();
> tail_thread--;
>
> return (*tail_thread)->seqNum;
> }
> */