From 1814a85a055732baf98fd030441bb4c5c5db9bdc Mon Sep 17 00:00:00 2001 From: Andreas Sandberg Date: Mon, 7 Jan 2013 13:05:46 -0500 Subject: 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. --- src/cpu/o3/lsq_impl.hh | 73 +++++++++++++++++++++++++++++++++++++++++++++++--- 1 file changed, 70 insertions(+), 3 deletions(-) (limited to 'src/cpu/o3/lsq_impl.hh') diff --git a/src/cpu/o3/lsq_impl.hh b/src/cpu/o3/lsq_impl.hh index 7051c9f7c..c796d7078 100644 --- a/src/cpu/o3/lsq_impl.hh +++ b/src/cpu/o3/lsq_impl.hh @@ -45,6 +45,7 @@ #include #include "cpu/o3/lsq.hh" +#include "debug/Drain.hh" #include "debug/Fetch.hh" #include "debug/LSQ.hh" #include "debug/Writeback.hh" @@ -143,11 +144,36 @@ LSQ::setActiveThreads(list *at_ptr) template void -LSQ::switchOut() +LSQ::drainSanityCheck() const { - for (ThreadID tid = 0; tid < numThreads; tid++) { - thread[tid].switchOut(); + assert(isDrained()); + + for (ThreadID tid = 0; tid < numThreads; tid++) + thread[tid].drainSanityCheck(); +} + +template +bool +LSQ::isDrained() const +{ + bool drained(true); + + if (!lqEmpty()) { + DPRINTF(Drain, "Not drained, LQ not empty.\n"); + drained = false; + } + + if (!sqEmpty()) { + DPRINTF(Drain, "Not drained, SQ not empty.\n"); + drained = false; + } + + if (retryTid != InvalidThreadID) { + DPRINTF(Drain, "Not drained, the LSQ has blocked the caches.\n"); + drained = false; } + + return drained; } template @@ -456,6 +482,47 @@ LSQ::isFull(ThreadID tid) return thread[tid].lqFull() || thread[tid].sqFull(); } +template +bool +LSQ::isEmpty() const +{ + return lqEmpty() && sqEmpty(); +} + +template +bool +LSQ::lqEmpty() const +{ + list::const_iterator threads = activeThreads->begin(); + list::const_iterator end = activeThreads->end(); + + while (threads != end) { + ThreadID tid = *threads++; + + if (!thread[tid].lqEmpty()) + return false; + } + + return true; +} + +template +bool +LSQ::sqEmpty() const +{ + list::const_iterator threads = activeThreads->begin(); + list::const_iterator end = activeThreads->end(); + + while (threads != end) { + ThreadID tid = *threads++; + + if (!thread[tid].sqEmpty()) + return false; + } + + return true; +} + template bool LSQ::lqFull() -- cgit v1.2.3