cpu: Add writeback modeling for drain functionality

It is possible for the O3 CPU to consider itself drained and
later have a squashed instruction perform a writeback.  This
patch re-adds tracking of in-flight instructions to prevent
falsely signaling a drained event.
This commit is contained in:
Mitch Hayenga 2014-10-29 23:18:27 -05:00
parent 6847bbf7ce
commit 5bfa521c46
2 changed files with 9 additions and 1 deletions

View file

@ -437,6 +437,9 @@ class InstructionQueue
/** The number of physical registers in the CPU. */ /** The number of physical registers in the CPU. */
unsigned numPhysRegs; unsigned numPhysRegs;
/** Number of instructions currently in flight to FUs */
int wbOutstanding;
/** Delay between commit stage and the IQ. /** Delay between commit stage and the IQ.
* @todo: Make there be a distinction between the delays within IEW. * @todo: Make there be a distinction between the delays within IEW.
*/ */

View file

@ -415,6 +415,7 @@ InstructionQueue<Impl>::resetState()
deferredMemInsts.clear(); deferredMemInsts.clear();
blockedMemInsts.clear(); blockedMemInsts.clear();
retryMemInsts.clear(); retryMemInsts.clear();
wbOutstanding = 0;
} }
template <class Impl> template <class Impl>
@ -444,7 +445,9 @@ template <class Impl>
bool bool
InstructionQueue<Impl>::isDrained() const InstructionQueue<Impl>::isDrained() const
{ {
bool drained = dependGraph.empty() && instsToExecute.empty(); bool drained = dependGraph.empty() &&
instsToExecute.empty() &&
wbOutstanding == 0;
for (ThreadID tid = 0; tid < numThreads; ++tid) for (ThreadID tid = 0; tid < numThreads; ++tid)
drained = drained && memDepUnit[tid].isDrained(); drained = drained && memDepUnit[tid].isDrained();
@ -723,6 +726,7 @@ InstructionQueue<Impl>::processFUCompletion(DynInstPtr &inst, int fu_idx)
assert(!cpu->switchedOut()); assert(!cpu->switchedOut());
// The CPU could have been sleeping until this op completed (*extremely* // The CPU could have been sleeping until this op completed (*extremely*
// long latency op). Wake it if it was. This may be overkill. // long latency op). Wake it if it was. This may be overkill.
--wbOutstanding;
iewStage->wakeCPU(); iewStage->wakeCPU();
if (fu_idx > -1) if (fu_idx > -1)
@ -823,6 +827,7 @@ InstructionQueue<Impl>::scheduleReadyInsts()
} else { } else {
Cycles issue_latency = fuPool->getIssueLatency(op_class); Cycles issue_latency = fuPool->getIssueLatency(op_class);
// Generate completion event for the FU // Generate completion event for the FU
++wbOutstanding;
FUCompletion *execution = new FUCompletion(issuing_inst, FUCompletion *execution = new FUCompletion(issuing_inst,
idx, this); idx, this);