summaryrefslogtreecommitdiff
path: root/src/cpu/o3/commit_impl.hh
diff options
context:
space:
mode:
authorAndreas Sandberg <Andreas.Sandberg@ARM.com>2013-01-07 13:05:45 -0500
committerAndreas Sandberg <Andreas.Sandberg@ARM.com>2013-01-07 13:05:45 -0500
commit8db27aa230c40c21acf55fda3755ed173c34e47c (patch)
tree91bb4c589096c5a80907b5bc6cdae9b7e235d59a /src/cpu/o3/commit_impl.hh
parenta2077ccf026f4587bf097274b241aa2c78c096e9 (diff)
downloadgem5-8db27aa230c40c21acf55fda3755ed173c34e47c.tar.xz
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 (limited to 'src/cpu/o3/commit_impl.hh')
-rw-r--r--src/cpu/o3/commit_impl.hh50
1 files changed, 29 insertions, 21 deletions
diff --git a/src/cpu/o3/commit_impl.hh b/src/cpu/o3/commit_impl.hh
index bff5c5ae9..333ccc89f 100644
--- a/src/cpu/o3/commit_impl.hh
+++ b/src/cpu/o3/commit_impl.hh
@@ -144,6 +144,7 @@ DefaultCommit<Impl>::DefaultCommit(O3CPU *_cpu, DerivO3CPUParams *params)
tcSquash[tid] = false;
pc[tid].set(0);
lastCommitedSeqNum[tid] = 0;
+ squashAfterInst[tid] = NULL;
}
interrupt = NoFault;
}
@@ -404,6 +405,7 @@ DefaultCommit<Impl>::takeOverFrom()
changedROBNumEntries[tid] = false;
trapSquash[tid] = false;
tcSquash[tid] = false;
+ squashAfterInst[tid] = NULL;
}
squashCounter = 0;
rob->takeOverFrom();
@@ -587,31 +589,32 @@ DefaultCommit<Impl>::squashFromTC(ThreadID tid)
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;
-
- // Send back the sequence number of the squashed instruction.
- toIEW->commitInfo[tid].doneSeqNum = squash_after_seq_num;
-
- toIEW->commitInfo[tid].squashInst = head_inst;
- // Send back the squash signal to tell stages that they should squash.
- toIEW->commitInfo[tid].squash = true;
-
- // Send back the rob squashing signal so other stages know that
- // the ROB is in the process of squashing.
- toIEW->commitInfo[tid].robSquashing = 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;
- toIEW->commitInfo[tid].mispredictInst = NULL;
+ commitStatus[tid] = ROBSquashing;
+ cpu->activityThisCycle();
+}
- toIEW->commitInfo[tid].pc = pc[tid];
+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, squash_after_seq_num);
- commitStatus[tid] = ROBSquashing;
+ tid, head_inst->seqNum);
+
+ assert(!squashAfterInst[tid] || squashAfterInst[tid] == head_inst);
+ commitStatus[tid] = SquashAfterPending;
+ squashAfterInst[tid] = head_inst;
}
template <class Impl>
@@ -797,6 +800,11 @@ DefaultCommit<Impl>::commit()
} 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 @@ DefaultCommit<Impl>::commitInsts()
// 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;