diff options
Diffstat (limited to 'src/cpu')
-rw-r--r-- | src/cpu/o3/commit.hh | 47 | ||||
-rw-r--r-- | src/cpu/o3/commit_impl.hh | 50 |
2 files changed, 70 insertions, 27 deletions
diff --git a/src/cpu/o3/commit.hh b/src/cpu/o3/commit.hh index fdd9609a4..2d8d88b21 100644 --- a/src/cpu/o3/commit.hh +++ b/src/cpu/o3/commit.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 @@ -129,7 +129,8 @@ class DefaultCommit Idle, ROBSquashing, TrapPending, - FetchTrapPending + FetchTrapPending, + SquashAfterPending, //< Committing instructions before a squash. }; /** Commit policy for SMT mode. */ @@ -259,13 +260,38 @@ class DefaultCommit /** 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 @@ class DefaultCommit /** 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 --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; |