summaryrefslogtreecommitdiff
path: root/src/cpu/o3/rob_impl.hh
diff options
context:
space:
mode:
authorKevin Lim <ktlim@umich.edu>2006-05-30 14:17:41 -0400
committerKevin Lim <ktlim@umich.edu>2006-05-30 14:17:41 -0400
commit4a5b51b516853c9fcaabc44caacdd7e8e93dc0ef (patch)
tree4b7d92408a2b74a16ae6f7b4167ded00079355ef /src/cpu/o3/rob_impl.hh
parentd308055afc1ace1f321b76e8a85a9a45165da2ce (diff)
parentf1fab2a4469d6cb2e55ebac15da02f8c1fcb7055 (diff)
downloadgem5-4a5b51b516853c9fcaabc44caacdd7e8e93dc0ef.tar.xz
Merge ktlim@zizzer:/bk/m5
into zamp.eecs.umich.edu:/z/ktlim2/clean/newmem SConstruct: src/SConscript: src/arch/SConscript: src/arch/alpha/faults.cc: src/arch/alpha/tlb.cc: src/base/traceflags.py: src/cpu/SConscript: src/cpu/base.cc: src/cpu/base.hh: src/cpu/base_dyn_inst.cc: src/cpu/cpu_exec_context.cc: src/cpu/cpu_exec_context.hh: src/cpu/exec_context.hh: src/cpu/o3/alpha_cpu.hh: src/cpu/o3/alpha_cpu_impl.hh: src/cpu/o3/alpha_dyn_inst.hh: src/cpu/o3/cpu.cc: src/cpu/o3/cpu.hh: src/cpu/o3/regfile.hh: src/cpu/ozone/cpu.hh: src/cpu/simple/base.cc: src/cpu/base_dyn_inst.hh: src/cpu/o3/2bit_local_pred.cc: src/cpu/o3/2bit_local_pred.hh: src/cpu/o3/alpha_cpu.cc: src/cpu/o3/alpha_cpu_builder.cc: src/cpu/o3/alpha_dyn_inst.cc: src/cpu/o3/alpha_dyn_inst_impl.hh: src/cpu/o3/alpha_impl.hh: src/cpu/o3/alpha_params.hh: src/cpu/o3/bpred_unit.cc: src/cpu/o3/bpred_unit.hh: src/cpu/o3/bpred_unit_impl.hh: src/cpu/o3/btb.cc: src/cpu/o3/btb.hh: src/cpu/o3/comm.hh: src/cpu/o3/commit.cc: src/cpu/o3/commit.hh: src/cpu/o3/commit_impl.hh: src/cpu/o3/cpu_policy.hh: src/cpu/o3/decode.cc: src/cpu/o3/decode.hh: src/cpu/o3/decode_impl.hh: src/cpu/o3/fetch.cc: src/cpu/o3/fetch.hh: src/cpu/o3/fetch_impl.hh: src/cpu/o3/free_list.cc: src/cpu/o3/free_list.hh: src/cpu/o3/iew.cc: src/cpu/o3/iew.hh: src/cpu/o3/iew_impl.hh: src/cpu/o3/inst_queue.cc: src/cpu/o3/inst_queue.hh: src/cpu/o3/inst_queue_impl.hh: src/cpu/o3/mem_dep_unit.cc: src/cpu/o3/mem_dep_unit.hh: src/cpu/o3/mem_dep_unit_impl.hh: src/cpu/o3/ras.cc: src/cpu/o3/ras.hh: src/cpu/o3/rename.cc: src/cpu/o3/rename.hh: src/cpu/o3/rename_impl.hh: src/cpu/o3/rename_map.cc: src/cpu/o3/rename_map.hh: src/cpu/o3/rob.cc: src/cpu/o3/rob.hh: src/cpu/o3/rob_impl.hh: src/cpu/o3/sat_counter.cc: src/cpu/o3/sat_counter.hh: src/cpu/o3/store_set.cc: src/cpu/o3/store_set.hh: src/cpu/o3/tournament_pred.cc: src/cpu/o3/tournament_pred.hh: Hand merges. --HG-- rename : build/SConstruct => SConstruct rename : SConscript => src/SConscript rename : arch/alpha/ev5.cc => src/arch/alpha/ev5.cc rename : arch/alpha/isa/decoder.isa => src/arch/alpha/isa/decoder.isa rename : arch/alpha/isa/pal.isa => src/arch/alpha/isa/pal.isa rename : base/traceflags.py => src/base/traceflags.py rename : cpu/SConscript => src/cpu/SConscript rename : cpu/base.cc => src/cpu/base.cc rename : cpu/base.hh => src/cpu/base.hh rename : cpu/base_dyn_inst.cc => src/cpu/base_dyn_inst.cc rename : cpu/base_dyn_inst.hh => src/cpu/base_dyn_inst.hh rename : cpu/cpu_exec_context.cc => src/cpu/cpu_exec_context.cc rename : cpu/cpu_exec_context.hh => src/cpu/cpu_exec_context.hh rename : cpu/cpu_models.py => src/cpu/cpu_models.py rename : cpu/exec_context.hh => src/cpu/exec_context.hh rename : cpu/exetrace.cc => src/cpu/exetrace.cc rename : cpu/exetrace.hh => src/cpu/exetrace.hh rename : cpu/inst_seq.hh => src/cpu/inst_seq.hh rename : cpu/o3/2bit_local_pred.cc => src/cpu/o3/2bit_local_pred.cc rename : cpu/o3/2bit_local_pred.hh => src/cpu/o3/2bit_local_pred.hh rename : cpu/o3/alpha_cpu.hh => src/cpu/o3/alpha_cpu.hh rename : cpu/o3/alpha_cpu_builder.cc => src/cpu/o3/alpha_cpu_builder.cc rename : cpu/o3/alpha_cpu_impl.hh => src/cpu/o3/alpha_cpu_impl.hh rename : cpu/o3/alpha_dyn_inst.hh => src/cpu/o3/alpha_dyn_inst.hh rename : cpu/o3/alpha_dyn_inst_impl.hh => src/cpu/o3/alpha_dyn_inst_impl.hh rename : cpu/o3/alpha_impl.hh => src/cpu/o3/alpha_impl.hh rename : cpu/o3/alpha_params.hh => src/cpu/o3/alpha_params.hh rename : cpu/o3/bpred_unit.cc => src/cpu/o3/bpred_unit.cc rename : cpu/o3/bpred_unit.hh => src/cpu/o3/bpred_unit.hh rename : cpu/o3/bpred_unit_impl.hh => src/cpu/o3/bpred_unit_impl.hh rename : cpu/o3/btb.cc => src/cpu/o3/btb.cc rename : cpu/o3/btb.hh => src/cpu/o3/btb.hh rename : cpu/o3/comm.hh => src/cpu/o3/comm.hh rename : cpu/o3/commit.cc => src/cpu/o3/commit.cc rename : cpu/o3/commit.hh => src/cpu/o3/commit.hh rename : cpu/o3/commit_impl.hh => src/cpu/o3/commit_impl.hh rename : cpu/o3/cpu.cc => src/cpu/o3/cpu.cc rename : cpu/o3/cpu.hh => src/cpu/o3/cpu.hh rename : cpu/o3/cpu_policy.hh => src/cpu/o3/cpu_policy.hh rename : cpu/o3/decode.cc => src/cpu/o3/decode.cc rename : cpu/o3/decode.hh => src/cpu/o3/decode.hh rename : cpu/o3/decode_impl.hh => src/cpu/o3/decode_impl.hh rename : cpu/o3/fetch.cc => src/cpu/o3/fetch.cc rename : cpu/o3/fetch.hh => src/cpu/o3/fetch.hh rename : cpu/o3/fetch_impl.hh => src/cpu/o3/fetch_impl.hh rename : cpu/o3/free_list.cc => src/cpu/o3/free_list.cc rename : cpu/o3/free_list.hh => src/cpu/o3/free_list.hh rename : cpu/o3/iew.cc => src/cpu/o3/iew.cc rename : cpu/o3/iew.hh => src/cpu/o3/iew.hh rename : cpu/o3/iew_impl.hh => src/cpu/o3/iew_impl.hh rename : cpu/o3/inst_queue.cc => src/cpu/o3/inst_queue.cc rename : cpu/o3/inst_queue.hh => src/cpu/o3/inst_queue.hh rename : cpu/o3/inst_queue_impl.hh => src/cpu/o3/inst_queue_impl.hh rename : cpu/o3/mem_dep_unit.cc => src/cpu/o3/mem_dep_unit.cc rename : cpu/o3/mem_dep_unit.hh => src/cpu/o3/mem_dep_unit.hh rename : cpu/o3/mem_dep_unit_impl.hh => src/cpu/o3/mem_dep_unit_impl.hh rename : cpu/o3/ras.cc => src/cpu/o3/ras.cc rename : cpu/o3/ras.hh => src/cpu/o3/ras.hh rename : cpu/o3/regfile.hh => src/cpu/o3/regfile.hh rename : cpu/o3/rename.cc => src/cpu/o3/rename.cc rename : cpu/o3/rename.hh => src/cpu/o3/rename.hh rename : cpu/o3/rename_impl.hh => src/cpu/o3/rename_impl.hh rename : cpu/o3/rename_map.cc => src/cpu/o3/rename_map.cc rename : cpu/o3/rename_map.hh => src/cpu/o3/rename_map.hh rename : cpu/o3/rob.hh => src/cpu/o3/rob.hh rename : cpu/o3/rob_impl.hh => src/cpu/o3/rob_impl.hh rename : cpu/o3/sat_counter.hh => src/cpu/o3/sat_counter.hh rename : cpu/o3/store_set.cc => src/cpu/o3/store_set.cc rename : cpu/o3/store_set.hh => src/cpu/o3/store_set.hh rename : cpu/o3/tournament_pred.cc => src/cpu/o3/tournament_pred.cc rename : cpu/o3/tournament_pred.hh => src/cpu/o3/tournament_pred.hh rename : cpu/ozone/cpu.cc => src/cpu/ozone/cpu.cc rename : cpu/ozone/cpu.hh => src/cpu/ozone/cpu.hh rename : cpu/ozone/cpu_impl.hh => src/cpu/ozone/cpu_impl.hh rename : cpu/static_inst.hh => src/cpu/static_inst.hh rename : kern/system_events.cc => src/kern/system_events.cc rename : kern/tru64/tru64.hh => src/kern/tru64/tru64.hh rename : python/m5/objects/AlphaFullCPU.py => src/python/m5/objects/AlphaFullCPU.py rename : sim/pseudo_inst.cc => src/sim/pseudo_inst.cc extra : convert_revision : ff351fc0e3a7c0f23e59fdbec33d8209eb9280be
Diffstat (limited to 'src/cpu/o3/rob_impl.hh')
-rw-r--r--src/cpu/o3/rob_impl.hh621
1 files changed, 500 insertions, 121 deletions
diff --git a/src/cpu/o3/rob_impl.hh b/src/cpu/o3/rob_impl.hh
index e7a5671d9..25e0c80fd 100644
--- a/src/cpu/o3/rob_impl.hh
+++ b/src/cpu/o3/rob_impl.hh
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2004-2005 The Regents of The University of Michigan
+ * Copyright (c) 2004-2006 The Regents of The University of Michigan
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -26,20 +26,74 @@
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
-#ifndef __CPU_O3_CPU_ROB_IMPL_HH__
-#define __CPU_O3_CPU_ROB_IMPL_HH__
-
#include "config/full_system.hh"
#include "cpu/o3/rob.hh"
+using namespace std;
+
template <class Impl>
-ROB<Impl>::ROB(unsigned _numEntries, unsigned _squashWidth)
+ROB<Impl>::ROB(unsigned _numEntries, unsigned _squashWidth,
+ string _smtROBPolicy, unsigned _smtROBThreshold,
+ unsigned _numThreads)
: numEntries(_numEntries),
squashWidth(_squashWidth),
numInstsInROB(0),
- squashedSeqNum(0)
+ squashedSeqNum(0),
+ numThreads(_numThreads)
+{
+ 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}");
+ }
+}
+
+template <class Impl>
+std::string
+ROB<Impl>::name() const
{
- doneSquashing = true;
+ return cpu->name() + ".rob";
}
template <class Impl>
@@ -48,124 +102,227 @@ ROB<Impl>::setCPU(FullCPU *cpu_ptr)
{
cpu = cpu_ptr;
- // 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();
+ }
- // 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();
}
template <class Impl>
-int
-ROB<Impl>::countInsts()
+void
+ROB<Impl>::setActiveThreads(list<unsigned> *at_ptr)
{
- // 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;
+}
- // 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();
}
+}
- // 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();
+ }
+ numInstsInROB = 0;
+
+ // Initialize the "universal" ROB head & tail point to invalid
+ // pointers
+ head = instList[0].end();
+ tail = instList[0].end();
+}
+
+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;
+ }
+ }
}
+}
+
+template <class Impl>
+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;
- return return_val;
+ for (int i=0;i < numThreads;i++)
+ total += countInsts(i);
- // 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;
+ return total;
+}
+
+template <class Impl>
+int
+ROB<Impl>::countInsts(unsigned tid)
+{
+ return instList[tid].size();
}
template <class Impl>
void
ROB<Impl>::insertInst(DynInstPtr &inst)
{
- // Make sure we have the right number of instructions.
- assert(numInstsInROB == countInsts());
- // Make sure the instruction is valid.
+ //assert(numInstsInROB == countInsts());
assert(inst);
- 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());
- // If the ROB is full then exit.
assert(numInstsInROB != numEntries);
- ++numInstsInROB;
+ int tid = inst->threadNumber;
- // 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);
}
- // 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--;
- DPRINTF(ROB, "ROB: Now has %d instructions.\n", numInstsInROB);
+ inst->setInROB();
+
+ ++numInstsInROB;
+ ++threadEntries[tid];
+ assert((*tail) == inst);
+
+ DPRINTF(ROB, "[tid:%i] Now has %d instructions.\n", tid, threadEntries[tid]);
}
// Whatever calls this function needs to ensure that it properly frees up
// registers prior to this function.
+/*
template <class Impl>
void
ROB<Impl>::retireHead()
{
- assert(numInstsInROB == countInsts());
+ //assert(numInstsInROB == countInsts());
+ assert(numInstsInROB > 0);
+
+ 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);
// Get the head ROB instruction.
- DynInstPtr head_inst = cpu->instList.front();
+ InstIt head_it = instList[tid].begin();
+
+ DynInstPtr head_inst = (*head_it);
- // Make certain this can retire.
assert(head_inst->readyToCommit());
- 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(),
head_inst->seqNum);
- // Keep track of how many instructions are in the ROB.
--numInstsInROB;
+ --threadEntries[tid];
+
+ head_inst->removeInROB();
+ head_inst->setCommitted();
+
+ instList[tid].erase(head_it);
- // 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.
+ //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.
cpu->removeFrontInst(head_inst);
+}
+/*
+template <class Impl>
+bool
+ROB<Impl>::isHeadReady()
+{
+ if (numInstsInROB != 0) {
+ return (*head)->readyToCommit();
+ }
- 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();
}
+
+ return false;
}
template <class Impl>
bool
-ROB<Impl>::isHeadReady()
+ROB<Impl>::canCommit()
{
- 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;
+ }
}
return false;
@@ -175,131 +332,339 @@ template <class Impl>
unsigned
ROB<Impl>::numFreeEntries()
{
- assert(numInstsInROB == countInsts());
+ //assert(numInstsInROB == countInsts());
return numEntries - numInstsInROB;
}
template <class Impl>
+unsigned
+ROB<Impl>::numFreeEntries(unsigned tid)
+{
+ return maxEntries[tid] - threadEntries[tid];
+}
+
+template <class Impl>
void
-ROB<Impl>::doSquash()
+ROB<Impl>::doSquash(unsigned tid)
{
- DPRINTF(ROB, "ROB: Squashing instructions.\n");
+ DPRINTF(ROB, "[tid:%u]: Squashing instructions until [sn:%i].\n",
+ tid, squashedSeqNum);
+
+ assert(squashIt[tid] != instList[tid].end());
+
+ if ((*squashIt[tid])->seqNum < squashedSeqNum) {
+ DPRINTF(ROB, "[tid:%u]: Done squashing instructions.\n",
+ tid);
- assert(squashIt != cpu->instList.end());
+ squashIt[tid] = instList[tid].end();
+
+ doneSquashing[tid] = true;
+ return;
+ }
+
+ bool robTailUpdate = false;
for (int numSquashed = 0;
- numSquashed < squashWidth && (*squashIt)->seqNum != squashedSeqNum;
+ numSquashed < squashWidth &&
+ squashIt[tid] != instList[tid].end() &&
+ (*squashIt[tid])->seqNum > squashedSeqNum;
++numSquashed)
{
- // Ensure that the instruction is younger.
- assert((*squashIt)->seqNum > squashedSeqNum);
-
- DPRINTF(ROB, "ROB: Squashing instruction PC %#x, seq num %i.\n",
- (*squashIt)->readPC(), (*squashIt)->seqNum);
+ DPRINTF(ROB, "[tid:%u]: Squashing instruction PC %#x, seq num %i.\n",
+ (*squashIt[tid])->threadNumber,
+ (*squashIt[tid])->readPC(),
+ (*squashIt[tid])->seqNum);
// Mark the instruction as squashed, and ready to commit so that
// it can drain out of the pipeline.
- (*squashIt)->setSquashed();
-
- (*squashIt)->setCanCommit();
-
- // 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 "
+ (*squashIt[tid])->setSquashed();
+
+ (*squashIt[tid])->setCanCommit();
+
+
+ if (squashIt[tid] == instList[tid].begin()) {
+ DPRINTF(ROB, "Reached head of instruction list while "
"squashing.\n");
- squashIt = cpu->instList.end();
+ squashIt[tid] = instList[tid].end();
- doneSquashing = true;
+ doneSquashing[tid] = true;
return;
}
-#endif
- // 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]--;
}
// Check if ROB is done squashing.
- 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);
+
+ squashIt[tid] = instList[tid].end();
+
+ doneSquashing[tid] = true;
+ }
+
+ if (robTailUpdate) {
+ updateTail();
+ }
+}
+
+
+template <class Impl>
+void
+ROB<Impl>::updateHead()
+{
+ DynInstPtr head_inst;
+ InstSeqNum lowest_num = 0;
+ bool first_valid = true;
+
+ // @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();
+ }
- squashIt = cpu->instList.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;
+ }
- doneSquashing = true;
+ // 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)
+ROB<Impl>::squash(InstSeqNum squash_num,unsigned tid)
{
- DPRINTF(ROB, "ROB: Starting to squash within the ROB.\n");
- doneSquashing = false;
+ 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;
squashedSeqNum = squash_num;
- assert(tail != cpu->instList.end());
+ if (!instList[tid].empty()) {
+ InstIt tail_thread = instList[tid].end();
+ tail_thread--;
- squashIt = tail;
+ squashIt[tid] = tail_thread;
- doSquash();
+ doSquash(tid);
+ }
+}
+/*
+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();
+ assert((*head_thread)->isInROB()==true);
+
+ return *head_thread;
+ } else {
+ return dummyInst;
+ }
+}
+/*
template <class Impl>
uint64_t
ROB<Impl>::readHeadPC()
{
- assert(numInstsInROB == countInsts());
+ //assert(numInstsInROB == countInsts());
- DynInstPtr head_inst = cpu->instList.front();
+ DynInstPtr head_inst = *head;
return head_inst->readPC();
}
template <class Impl>
uint64_t
+ROB<Impl>::readHeadPC(unsigned tid)
+{
+ //assert(numInstsInROB == countInsts());
+ InstIt head_thread = instList[tid].begin();
+
+ return (*head_thread)->readPC();
+}
+
+
+template <class Impl>
+uint64_t
ROB<Impl>::readHeadNextPC()
{
- assert(numInstsInROB == countInsts());
+ //assert(numInstsInROB == countInsts());
- DynInstPtr head_inst = cpu->instList.front();
+ DynInstPtr head_inst = *head;
return head_inst->readNextPC();
}
template <class Impl>
+uint64_t
+ROB<Impl>::readHeadNextPC(unsigned tid)
+{
+ //assert(numInstsInROB == countInsts());
+ InstIt head_thread = instList[tid].begin();
+
+ return (*head_thread)->readNextPC();
+}
+
+template <class Impl>
InstSeqNum
ROB<Impl>::readHeadSeqNum()
{
- // 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;
return head_inst->seqNum;
}
template <class Impl>
+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>
uint64_t
ROB<Impl>::readTailPC()
{
- assert(numInstsInROB == countInsts());
+ //assert(numInstsInROB == countInsts());
- assert(tail != cpu->instList.end());
+ //assert(tail != instList[0].end());
return (*tail)->readPC();
}
template <class Impl>
+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>
InstSeqNum
ROB<Impl>::readTailSeqNum()
{
@@ -309,4 +674,18 @@ ROB<Impl>::readTailSeqNum()
return (*tail)->seqNum;
}
-#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;
+}
+*/