summaryrefslogtreecommitdiff
path: root/src/cpu/o3/rename_impl.hh
diff options
context:
space:
mode:
authorAndreas Sandberg <Andreas.Sandberg@ARM.com>2013-01-07 13:05:46 -0500
committerAndreas Sandberg <Andreas.Sandberg@ARM.com>2013-01-07 13:05:46 -0500
commit1814a85a055732baf98fd030441bb4c5c5db9bdc (patch)
tree33dd6adc62342a55ac3b0f4dbe9fdb9d82faa323 /src/cpu/o3/rename_impl.hh
parent9e8003148f78811e600e51a900f96b71cb525b60 (diff)
downloadgem5-1814a85a055732baf98fd030441bb4c5c5db9bdc.tar.xz
cpu: Rewrite O3 draining to avoid stopping in microcode
Previously, the O3 CPU could stop in the middle of a microcode sequence. This patch makes sure that the pipeline stops when it has committed a normal instruction or exited from a microcode sequence. Additionally, it makes sure that the pipeline has no instructions in flight when it is drained, which should make draining more robust. Draining is controlled in the commit stage, which checks if the next PC after a committed instruction is in microcode. If this isn't the case, it requests a squash of all instructions after that the instruction that just committed and immediately signals a drain stall to the fetch stage. The CPU then continues to execute until the pipeline and all associated buffers are empty.
Diffstat (limited to 'src/cpu/o3/rename_impl.hh')
-rw-r--r--src/cpu/o3/rename_impl.hh109
1 files changed, 38 insertions, 71 deletions
diff --git a/src/cpu/o3/rename_impl.hh b/src/cpu/o3/rename_impl.hh
index 4996cfcad..15a4ebc13 100644
--- a/src/cpu/o3/rename_impl.hh
+++ b/src/cpu/o3/rename_impl.hh
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2010 ARM Limited
+ * Copyright (c) 2010-2012 ARM Limited
* All rights reserved.
*
* The license below extends only to copyright in the software and shall
@@ -61,31 +61,9 @@ DefaultRename<Impl>::DefaultRename(O3CPU *_cpu, DerivO3CPUParams *params)
commitToRenameDelay(params->commitToRenameDelay),
renameWidth(params->renameWidth),
commitWidth(params->commitWidth),
- resumeSerialize(false),
- resumeUnblocking(false),
numThreads(params->numThreads),
maxPhysicalRegs(params->numPhysIntRegs + params->numPhysFloatRegs)
{
- _status = Inactive;
-
- for (ThreadID tid = 0; tid < numThreads; tid++) {
- renameStatus[tid] = Idle;
-
- freeEntries[tid].iqEntries = 0;
- freeEntries[tid].lsqEntries = 0;
- freeEntries[tid].robEntries = 0;
-
- stalls[tid].iew = false;
- stalls[tid].commit = false;
- serializeInst[tid] = NULL;
-
- instsInProgress[tid] = 0;
-
- emptyROB[tid] = true;
-
- serializeOnNextInst[tid] = false;
- }
-
// @todo: Make into a parameter.
skidBufferMax = (2 * (decodeToRenameDelay * params->decodeWidth)) + renameWidth;
}
@@ -230,12 +208,34 @@ template <class Impl>
void
DefaultRename<Impl>::startupStage()
{
+ resetStage();
+}
+
+template <class Impl>
+void
+DefaultRename<Impl>::resetStage()
+{
+ _status = Inactive;
+
+ resumeSerialize = false;
+ resumeUnblocking = false;
+
// Grab the number of free entries directly from the stages.
for (ThreadID tid = 0; tid < numThreads; tid++) {
+ renameStatus[tid] = Idle;
+
freeEntries[tid].iqEntries = iew_ptr->instQueue.numFreeEntries(tid);
freeEntries[tid].lsqEntries = iew_ptr->ldstQueue.numFreeEntries(tid);
freeEntries[tid].robEntries = commit_ptr->numROBFreeEntries(tid);
emptyROB[tid] = true;
+
+ stalls[tid].iew = false;
+ stalls[tid].commit = false;
+ serializeInst[tid] = NULL;
+
+ instsInProgress[tid] = 0;
+
+ serializeOnNextInst[tid] = false;
}
}
@@ -271,67 +271,34 @@ DefaultRename<Impl>::setScoreboard(Scoreboard *_scoreboard)
template <class Impl>
bool
-DefaultRename<Impl>::drain()
+DefaultRename<Impl>::isDrained() const
{
- // Rename is ready to switch out at any time.
- cpu->signalDrained();
+ for (ThreadID tid = 0; tid < numThreads; tid++) {
+ if (instsInProgress[tid] != 0 ||
+ !historyBuffer[tid].empty() ||
+ !skidBuffer[tid].empty() ||
+ !insts[tid].empty())
+ return false;
+ }
return true;
}
template <class Impl>
void
-DefaultRename<Impl>::switchOut()
+DefaultRename<Impl>::takeOverFrom()
{
- // Clear any state, fix up the rename map.
- for (ThreadID tid = 0; tid < numThreads; tid++) {
- typename std::list<RenameHistory>::iterator hb_it =
- historyBuffer[tid].begin();
-
- while (!historyBuffer[tid].empty()) {
- assert(hb_it != historyBuffer[tid].end());
-
- DPRINTF(Rename, "[tid:%u]: Removing history entry with sequence "
- "number %i.\n", tid, (*hb_it).instSeqNum);
-
- // Tell the rename map to set the architected register to the
- // previous physical register that it was renamed to.
- renameMap[tid]->setEntry(hb_it->archReg, hb_it->prevPhysReg);
-
- // Put the renamed physical register back on the free list.
- freeList->addReg(hb_it->newPhysReg);
-
- // Be sure to mark its register as ready if it's a misc register.
- if (hb_it->newPhysReg >= maxPhysicalRegs) {
- scoreboard->setReg(hb_it->newPhysReg);
- }
-
- historyBuffer[tid].erase(hb_it++);
- }
- insts[tid].clear();
- skidBuffer[tid].clear();
- }
+ resetStage();
}
template <class Impl>
void
-DefaultRename<Impl>::takeOverFrom()
+DefaultRename<Impl>::drainSanityCheck() const
{
- _status = Inactive;
- startupStage();
-
- // Reset all state prior to taking over from the other CPU.
for (ThreadID tid = 0; tid < numThreads; tid++) {
- renameStatus[tid] = Idle;
-
- stalls[tid].iew = false;
- stalls[tid].commit = false;
- serializeInst[tid] = NULL;
-
- instsInProgress[tid] = 0;
-
- emptyROB[tid] = true;
-
- serializeOnNextInst[tid] = false;
+ assert(historyBuffer[tid].empty());
+ assert(insts[tid].empty());
+ assert(skidBuffer[tid].empty());
+ assert(instsInProgress[tid] == 0);
}
}