/*
+ * Copyright (c) 2012, 2014 ARM Limited
+ * All rights reserved
+ *
+ * The license below extends only to copyright in the software and shall
+ * not be construed as granting a license to any other intellectual
+ * property including but not limited to intellectual property relating
+ * to a hardware implementation of the functionality of the software
+ * licensed hereunder. You may use the software subject to the license
+ * terms below provided that you ensure that this notice is replicated
+ * unmodified and in its entirety in all distributions of the software,
+ * modified or unmodified, in source code or in binary form.
+ *
* Copyright (c) 2004-2006 The Regents of The University of Michigan
* All rights reserved.
*
* Authors: Kevin Lim
*/
+#ifndef __CPU_O3_DECODE_IMPL_HH__
+#define __CPU_O3_DECODE_IMPL_HH__
+
#include "arch/types.hh"
#include "base/trace.hh"
#include "config/the_isa.hh"
#include "cpu/inst_seq.hh"
#include "debug/Activity.hh"
#include "debug/Decode.hh"
+#include "debug/O3PipeView.hh"
#include "params/DerivO3CPU.hh"
#include "sim/full_system.hh"
-using namespace std;
+// clang complains about std::set being overloaded with Packet::set if
+// we open up the entire namespace std
+using std::list;
template<class Impl>
DefaultDecode<Impl>::DefaultDecode(O3CPU *_cpu, DerivO3CPUParams *params)
fetchToDecodeDelay(params->fetchToDecodeDelay),
decodeWidth(params->decodeWidth),
numThreads(params->numThreads)
+{
+ if (decodeWidth > Impl::MaxWidth)
+ fatal("decodeWidth (%d) is larger than compiled limit (%d),\n"
+ "\tincrease MaxWidth in src/cpu/o3/impl.hh\n",
+ decodeWidth, static_cast<int>(Impl::MaxWidth));
+
+ // @todo: Make into a parameter
+ skidBufferMax = (fetchToDecodeDelay + 1) * params->fetchWidth;
+}
+
+template<class Impl>
+void
+DefaultDecode<Impl>::startupStage()
+{
+ resetStage();
+}
+
+template<class Impl>
+void
+DefaultDecode<Impl>::resetStage()
{
_status = Inactive;
decodeStatus[tid] = Idle;
stalls[tid].rename = false;
- stalls[tid].iew = false;
- stalls[tid].commit = false;
}
-
- // @todo: Make into a parameter
- skidBufferMax = (fetchToDecodeDelay * params->fetchWidth) + decodeWidth;
}
template <class Impl>
}
template <class Impl>
-bool
-DefaultDecode<Impl>::drain()
+void
+DefaultDecode<Impl>::drainSanityCheck() const
{
- // Decode is done draining at any time.
- cpu->signalDrained();
- return true;
+ for (ThreadID tid = 0; tid < numThreads; ++tid) {
+ assert(insts[tid].empty());
+ assert(skidBuffer[tid].empty());
+ }
}
template <class Impl>
-void
-DefaultDecode<Impl>::takeOverFrom()
+bool
+DefaultDecode<Impl>::isDrained() const
{
- _status = Inactive;
-
- // Be sure to reset state and clear out any old instructions.
for (ThreadID tid = 0; tid < numThreads; ++tid) {
- decodeStatus[tid] = Idle;
-
- stalls[tid].rename = false;
- stalls[tid].iew = false;
- stalls[tid].commit = false;
- while (!insts[tid].empty())
- insts[tid].pop();
- while (!skidBuffer[tid].empty())
- skidBuffer[tid].pop();
- branchCount[tid] = 0;
+ if (!insts[tid].empty() || !skidBuffer[tid].empty() ||
+ (decodeStatus[tid] != Running && decodeStatus[tid] != Idle))
+ return false;
}
- wroteToTimeBuffer = false;
+ return true;
}
template<class Impl>
if (stalls[tid].rename) {
DPRINTF(Decode,"[tid:%i]: Stall fom Rename stage detected.\n", tid);
ret_val = true;
- } else if (stalls[tid].iew) {
- DPRINTF(Decode,"[tid:%i]: Stall fom IEW stage detected.\n", tid);
- ret_val = true;
- } else if (stalls[tid].commit) {
- DPRINTF(Decode,"[tid:%i]: Stall fom Commit stage detected.\n", tid);
- ret_val = true;
}
return ret_val;
// Set the status to Blocked.
decodeStatus[tid] = Blocked;
- if (decodeStatus[tid] != Unblocking) {
+ if (toFetch->decodeUnblock[tid]) {
+ toFetch->decodeUnblock[tid] = false;
+ } else {
toFetch->decodeBlock[tid] = true;
wroteToTimeBuffer = true;
}
template<class Impl>
void
-DefaultDecode<Impl>::squash(DynInstPtr &inst, ThreadID tid)
+DefaultDecode<Impl>::squash(const DynInstPtr &inst, ThreadID tid)
{
DPRINTF(Decode, "[tid:%i]: [sn:%i] Squashing due to incorrect branch "
"prediction detected at decode.\n", tid, inst->seqNum);
// Send back mispredict information.
toFetch->decodeInfo[tid].branchMispredict = true;
toFetch->decodeInfo[tid].predIncorrect = true;
+ toFetch->decodeInfo[tid].mispredictInst = inst;
toFetch->decodeInfo[tid].squash = true;
toFetch->decodeInfo[tid].doneSeqNum = inst->seqNum;
toFetch->decodeInfo[tid].nextPC = inst->branchTarget();
toFetch->decodeInfo[tid].branchTaken = inst->pcState().branching();
toFetch->decodeInfo[tid].squashInst = inst;
+ if (toFetch->decodeInfo[tid].mispredictInst->isUncondCtrl()) {
+ toFetch->decodeInfo[tid].branchTaken = true;
+ }
InstSeqNum squash_seq_num = inst->seqNum;
assert(tid == inst->threadNumber);
- DPRINTF(Decode,"Inserting [sn:%lli] PC: %s into decode skidBuffer %i\n",
- inst->seqNum, inst->pcState(), inst->threadNumber);
-
skidBuffer[tid].push(inst);
+
+ DPRINTF(Decode,"Inserting [tid:%d][sn:%lli] PC: %s into decode skidBuffer %i\n",
+ inst->threadNumber, inst->seqNum, inst->pcState(), skidBuffer[tid].size());
}
// @todo: Eventually need to enforce this by not letting a thread
DefaultDecode<Impl>::sortInsts()
{
int insts_from_fetch = fromFetch->size;
-#ifdef DEBUG
- for (ThreadID tid = 0; tid < numThreads; tid++)
- assert(insts[tid].empty());
-#endif
for (int i = 0; i < insts_from_fetch; ++i) {
insts[fromFetch->insts[i]->threadNumber].push(fromFetch->insts[i]);
}
assert(stalls[tid].rename);
stalls[tid].rename = false;
}
-
- if (fromIEW->iewBlock[tid]) {
- stalls[tid].iew = true;
- }
-
- if (fromIEW->iewUnblock[tid]) {
- assert(stalls[tid].iew);
- stalls[tid].iew = false;
- }
-
- if (fromCommit->commitBlock[tid]) {
- stalls[tid].commit = true;
- }
-
- if (fromCommit->commitUnblock[tid]) {
- assert(stalls[tid].commit);
- stalls[tid].commit = false;
- }
}
template <class Impl>
return true;
}
- // Check ROB squash signals from commit.
- if (fromCommit->commitInfo[tid].robSquashing) {
- DPRINTF(Decode, "[tid:%u]: ROB is still squashing.\n", tid);
-
- // Continue to squash.
- decodeStatus[tid] = Squashing;
-
- return true;
- }
-
if (checkStall(tid)) {
return block(tid);
}
++decodeRunCycles;
}
- DynInstPtr inst;
-
std::queue<DynInstPtr>
&insts_to_decode = decodeStatus[tid] == Unblocking ?
skidBuffer[tid] : insts[tid];
while (insts_available > 0 && toRenameIndex < decodeWidth) {
assert(!insts_to_decode.empty());
- inst = insts_to_decode.front();
+ DynInstPtr inst = std::move(insts_to_decode.front());
insts_to_decode.pop();
--insts_available;
#if TRACING_ON
- inst->decodeTick = curTick();
+ if (DTRACE(O3PipeView)) {
+ inst->decodeTick = curTick() - inst->fetchTick;
+ }
#endif
// Ensure that if it was predicted as a branch, it really is a
}
// Go ahead and compute any PC-relative branches.
- if (inst->isDirectCtrl() && inst->isUncondCtrl()) {
+ // This includes direct unconditional control and
+ // direct conditional control that is predicted taken.
+ if (inst->isDirectCtrl() &&
+ (inst->isUncondCtrl() || inst->readPredTaken()))
+ {
++decodeBranchResolved;
if (!(inst->branchTarget() == inst->readPredTarg())) {
wroteToTimeBuffer = true;
}
}
+
+#endif//__CPU_O3_DECODE_IMPL_HH__