summaryrefslogtreecommitdiff
path: root/src/cpu/minor/execute.cc
diff options
context:
space:
mode:
authorAndrew Lukefahr <lukefahr@umich.edu>2014-11-06 05:42:21 -0600
committerAndrew Lukefahr <lukefahr@umich.edu>2014-11-06 05:42:21 -0600
commitbd32d55a2c457e7e68c1462d05fa126aa131a21a (patch)
treed0455fdf65c3de7d87f3163f2ec5563035bf30a1 /src/cpu/minor/execute.cc
parenta75e27b4a64df780e9b8207e10f3a11f172d1db3 (diff)
downloadgem5-bd32d55a2c457e7e68c1462d05fa126aa131a21a.tar.xz
cpu: Minor Draining Bug
Fixes a bug where Minor drains in the midst of committing a conditional store. While committing a conditional store, lastCommitWasEndOfMacroop is true (from the previous instruction) as we still haven't finished the conditional store. If a drain occurs before the cache response, Minor would check just lastCommitWasEndOfMacroop, which was true, and set drainState=DrainHaltFetch, which increases the streamSeqNum. This caused the conditional store to be squashed when the memory responded and it completed. However, to the memory the store succeeded, while to the instruction sequence it never occurred. In the case of an LLSC, the instruction sequence will replay the squashed STREX, which will fail as the cache is no longer in LLSC. Then the instruction sequence will loop back to a LDREX, which receives the updated (incorrect) value. Committed by: Nilay Vaish <nilay@cs.wisc.edu>
Diffstat (limited to 'src/cpu/minor/execute.cc')
-rw-r--r--src/cpu/minor/execute.cc9
1 files changed, 5 insertions, 4 deletions
diff --git a/src/cpu/minor/execute.cc b/src/cpu/minor/execute.cc
index 5f840a273..123128358 100644
--- a/src/cpu/minor/execute.cc
+++ b/src/cpu/minor/execute.cc
@@ -1683,10 +1683,11 @@ Execute::drain()
if (drainState == NotDraining) {
cpu.wakeupOnEvent(Pipeline::ExecuteStageId);
- /* Go to DrainCurrentInst if we're not between operations
- * this should probably test the LSQ as well. Or maybe
- * just always go to DrainCurrentInst anyway */
- if (lastCommitWasEndOfMacroop)
+ /* Go to DrainCurrentInst if we're between microops
+ * or waiting on an unbufferable memory operation.
+ * Otherwise we can go straight to DrainHaltFetch
+ */
+ if (isInbetweenInsts())
setDrainState(DrainHaltFetch);
else
setDrainState(DrainCurrentInst);