summaryrefslogtreecommitdiff
path: root/src/cpu/o3
diff options
context:
space:
mode:
authorMarco Elver <marco.elver@ed.ac.uk>2014-03-25 13:15:04 -0500
committerMarco Elver <marco.elver@ed.ac.uk>2014-03-25 13:15:04 -0500
commitb884fcf412f43ae8e1d365f23846f0f8e912ef1a (patch)
tree741591b9c7fb8b5bca3773e94d874630936c52a3 /src/cpu/o3
parent8b4b1dcb86b0799a8c32056427581a8b6249a3bf (diff)
downloadgem5-b884fcf412f43ae8e1d365f23846f0f8e912ef1a.tar.xz
cpu: o3: lsq: Fix TSO implementation
This patch fixes violation of TSO in the O3CPU, as all loads must be ordered with all other loads. In the LQ, if a snoop is observed, all subsequent loads need to be squashed if the system is TSO. Prior to this patch, the following case could be violated: P0 | P1 ; MOV [x],mail=/usr/spool/mail/nilay | MOV EAX,[y] ; MOV [y],mail=/usr/spool/mail/nilay | MOV EBX,[x] ; exists (1:EAX=1 /\ 1:EBX=0) [is a violation] The problem was found using litmus [http://diy.inria.fr]. Committed by: Nilay Vaish <nilay@cs.wisc.edu
Diffstat (limited to 'src/cpu/o3')
-rw-r--r--src/cpu/o3/lsq_unit_impl.hh12
1 files changed, 10 insertions, 2 deletions
diff --git a/src/cpu/o3/lsq_unit_impl.hh b/src/cpu/o3/lsq_unit_impl.hh
index 322a6704a..89c30aa46 100644
--- a/src/cpu/o3/lsq_unit_impl.hh
+++ b/src/cpu/o3/lsq_unit_impl.hh
@@ -464,6 +464,8 @@ LSQUnit<Impl>::checkSnoop(PacketPtr pkt)
incrLdIdx(load_idx);
+ bool force_squash = false;
+
while (load_idx != loadTail) {
DynInstPtr ld_inst = loadQueue[load_idx];
@@ -476,8 +478,14 @@ LSQUnit<Impl>::checkSnoop(PacketPtr pkt)
DPRINTF(LSQUnit, "-- inst [sn:%lli] load_addr: %#x to pktAddr:%#x\n",
ld_inst->seqNum, load_addr, invalidate_addr);
- if (load_addr == invalidate_addr) {
- if (ld_inst->possibleLoadViolation()) {
+ if (load_addr == invalidate_addr || force_squash) {
+ if (needsTSO) {
+ // If we have a TSO system, as all loads must be ordered with
+ // all other loads, this load as well as *all* subsequent loads
+ // need to be squashed to prevent possible load reordering.
+ force_squash = true;
+ }
+ if (ld_inst->possibleLoadViolation() || force_squash) {
DPRINTF(LSQUnit, "Conflicting load at addr %#x [sn:%lli]\n",
pkt->getAddr(), ld_inst->seqNum);