changeset 8088e94a9de0 in /z/repo/gem5
details: http://repo.gem5.org/gem5?cmd=changeset;node=8088e94a9de0
description:
cpu: Fix broken squashAfter implementation in O3 CPU
Commit can currently both commit and squash in the same cycle. This
confuses other stages since the signals coming from the commit stage
can only signal either a squash or a commit in a cycle. This changeset
changes the behavior of squashAfter so that it commits all
instructions, including the instruction that requested the squash, in
the first cycle and then starts to squash in the next cycle.
diffstat:
src/cpu/o3/commit.hh | 47 ++++++++++++++++++++++++++++++++++++++-----
src/cpu/o3/commit_impl.hh | 50 +++++++++++++++++++++++++++-------------------
2 files changed, 70 insertions(+), 27 deletions(-)
diffs (172 lines):
diff -r 4a0223da4924 -r 8088e94a9de0 src/cpu/o3/commit.hh
--- a/src/cpu/o3/commit.hh Mon Jan 07 13:05:45 2013 -0500
+++ b/src/cpu/o3/commit.hh Mon Jan 07 13:05:45 2013 -0500
@@ -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
@@ -129,7 +129,8 @@
Idle,
ROBSquashing,
TrapPending,
- FetchTrapPending
+ FetchTrapPending,
+ SquashAfterPending, //< Committing instructions before a squash.
};
/** Commit policy for SMT mode. */
@@ -259,13 +260,38 @@
/** Handles squashing due to an TC write. */
void squashFromTC(ThreadID tid);
- /** Handles squashing from instruction with SquashAfter set.
+ /** Handles a squash from a squashAfter() request. */
+ void squashFromSquashAfter(ThreadID tid);
+
+ /**
+ * Handle squashing from instruction with SquashAfter set.
+ *
* This differs from the other squashes as it squashes following
* instructions instead of the current instruction and doesn't
- * clean up various status bits about traps/tc writes pending.
+ * clean up various status bits about traps/tc writes
+ * pending. Since there might have been instructions committed by
+ * the commit stage before the squashing instruction was reached
+ * and we can't commit and squash in the same cycle, we have to
+ * squash in two steps:
+ *
+ * <ol>
+ * <li>Immediately set the commit status of the thread of
+ * SquashAfterPending. This forces the thread to stop
+ * committing instructions in this cycle. The last
+ * instruction to be committed in this cycle will be the
+ * SquashAfter instruction.
+ * <li>In the next cycle, commit() checks for the
+ * SquashAfterPending state and squashes <i>all</i>
+ * in-flight instructions. Since the SquashAfter instruction
+ * was the last instruction to be committed in the previous
+ * cycle, this causes all subsequent instructions to be
+ * squashed.
+ * </ol>
+ *
+ * @param tid ID of the thread to squash.
+ * @param head_inst Instruction that requested the squash.
*/
- void squashAfter(ThreadID tid, DynInstPtr &head_inst,
- uint64_t squash_after_seq_num);
+ void squashAfter(ThreadID tid, DynInstPtr &head_inst);
/** Handles processing an interrupt. */
void handleInterrupt();
@@ -372,6 +398,15 @@
/** Records if a thread has to squash this cycle due to an XC write. */
bool tcSquash[Impl::MaxThreads];
+ /**
+ * Instruction passed to squashAfter().
+ *
+ * The squash after implementation needs to buffer the instruction
+ * that caused a squash since this needs to be passed to the fetch
+ * stage once squashing starts.
+ */
+ DynInstPtr squashAfterInst[Impl::MaxThreads];
+
/** Priority List used for Commit Policy */
std::list<ThreadID> priority_list;
diff -r 4a0223da4924 -r 8088e94a9de0 src/cpu/o3/commit_impl.hh
--- a/src/cpu/o3/commit_impl.hh Mon Jan 07 13:05:45 2013 -0500
+++ b/src/cpu/o3/commit_impl.hh Mon Jan 07 13:05:45 2013 -0500
@@ -144,6 +144,7 @@
tcSquash[tid] = false;
pc[tid].set(0);
lastCommitedSeqNum[tid] = 0;
+ squashAfterInst[tid] = NULL;
}
interrupt = NoFault;
}
@@ -404,6 +405,7 @@
changedROBNumEntries[tid] = false;
trapSquash[tid] = false;
tcSquash[tid] = false;
+ squashAfterInst[tid] = NULL;
}
squashCounter = 0;
rob->takeOverFrom();
@@ -587,31 +589,32 @@
template <class Impl>
void
-DefaultCommit<Impl>::squashAfter(ThreadID tid, DynInstPtr &head_inst,
- uint64_t squash_after_seq_num)
+DefaultCommit<Impl>::squashFromSquashAfter(ThreadID tid)
{
- youngestSeqNum[tid] = squash_after_seq_num;
+ DPRINTF(Commit, "Squashing after squash after request, "
+ "restarting at PC %s\n", pc[tid]);
- rob->squash(squash_after_seq_num, tid);
- changedROBNumEntries[tid] = true;
+ squashAll(tid);
+ // Make sure to inform the fetch stage of which instruction caused
+ // the squash. It'll try to re-fetch an instruction executing in
+ // microcode unless this is set.
+ toIEW->commitInfo[tid].squashInst = squashAfterInst[tid];
+ squashAfterInst[tid] = NULL;
- // Send back the sequence number of the squashed instruction.
- toIEW->commitInfo[tid].doneSeqNum = squash_after_seq_num;
+ commitStatus[tid] = ROBSquashing;
+ cpu->activityThisCycle();
+}
- toIEW->commitInfo[tid].squashInst = head_inst;
- // Send back the squash signal to tell stages that they should squash.
- toIEW->commitInfo[tid].squash = true;
+template <class Impl>
+void
+DefaultCommit<Impl>::squashAfter(ThreadID tid, DynInstPtr &head_inst)
+{
+ DPRINTF(Commit, "Executing squash after for [tid:%i] inst [sn:%lli]\n",
+ tid, head_inst->seqNum);
- // Send back the rob squashing signal so other stages know that
- // the ROB is in the process of squashing.
- toIEW->commitInfo[tid].robSquashing = true;
-
- toIEW->commitInfo[tid].mispredictInst = NULL;
-
- toIEW->commitInfo[tid].pc = pc[tid];
- DPRINTF(Commit, "Executing squash after for [tid:%i] inst [sn:%lli]\n",
- tid, squash_after_seq_num);
- commitStatus[tid] = ROBSquashing;
+ assert(!squashAfterInst[tid] || squashAfterInst[tid] == head_inst);
+ commitStatus[tid] = SquashAfterPending;
+ squashAfterInst[tid] = head_inst;
}
template <class Impl>
@@ -797,6 +800,11 @@
} else if (tcSquash[tid] == true) {
assert(commitStatus[tid] != TrapPending);
squashFromTC(tid);
+ } else if (commitStatus[tid] == SquashAfterPending) {
+ // A squash from the previous cycle of the commit stage (i.e.,
+ // commitInsts() called squashAfter) is pending. Squash the
+ // thread now.
+ squashFromSquashAfter(tid);
}
// Squashed sequence number must be older than youngest valid
@@ -1008,7 +1016,7 @@
// If this is an instruction that doesn't play nicely with
// others squash everything and restart fetch
if (head_inst->isSquashAfter())
- squashAfter(tid, head_inst, head_inst->seqNum);
+ squashAfter(tid, head_inst);
int count = 0;
Addr oldpc;
_______________________________________________
gem5-dev mailing list
[email protected]
http://m5sim.org/mailman/listinfo/gem5-dev