O3 CPU LSQ: Implement TSO
authorNilay Vaish <nilay@cs.wisc.edu>
Sun, 29 Jan 2012 01:09:04 +0000 (19:09 -0600)
committerNilay Vaish <nilay@cs.wisc.edu>
Sun, 29 Jan 2012 01:09:04 +0000 (19:09 -0600)
This patch makes O3's LSQ maintain total order between stores. Essentially
only the store at the head of the store buffer is allowed to be in flight.
Only after that store completes, the next store is issued to the memory
system. By default, the x86 architecture will have TSO.

src/cpu/o3/O3CPU.py
src/cpu/o3/lsq_unit.hh
src/cpu/o3/lsq_unit_impl.hh

index 9dfcc8b9eb09f6efa04e4ff9f89402a9d6ed6636..6f721a11bbfa5b894f5077f5932d47232360ccaa 100644 (file)
@@ -143,3 +143,5 @@ class DerivO3CPU(BaseCPU):
     smtROBThreshold = Param.Int(100, "SMT ROB Threshold Sharing Parameter")
     smtCommitPolicy = Param.String('RoundRobin', "SMT Commit Policy")
 
+    needsTSO = Param.Bool(buildEnv['TARGET_ISA'] == 'x86',
+                          "Enable TSO Memory model")
index 3c1af4533b36cb98ac64ba34e340aa8015ef5a04..a11d95f3badc209034147d328480db7aedb04bf5 100644 (file)
@@ -453,6 +453,9 @@ class LSQUnit {
     /** Has the blocked load been handled. */
     bool loadBlockedHandled;
 
+    /** Whether or not a store is in flight. */
+    bool storeInFlight;
+
     /** The sequence number of the blocked load. */
     InstSeqNum blockedLoadSeqNum;
 
@@ -466,6 +469,9 @@ class LSQUnit {
     /** The packet that is pending free cache ports. */
     PacketPtr pendingPkt;
 
+    /** Flag for memory model. */
+    bool needsTSO;
+
     // Will also need how many read/write ports the Dcache has.  Or keep track
     // of that in stage that is one level up, and only call executeLoad/Store
     // the appropriate number of times.
index a0452b4ae853f205d85adc888386b3976e8b1aa0..d0db6f6fe7a511077b7e6915a0728eba5d8f8b7c 100644 (file)
@@ -138,7 +138,7 @@ template <class Impl>
 LSQUnit<Impl>::LSQUnit()
     : loads(0), stores(0), storesToWB(0), cacheBlockMask(0), stalled(false),
       isStoreBlocked(false), isLoadBlocked(false),
-      loadBlockedHandled(false), hasPendingPkt(false)
+      loadBlockedHandled(false), storeInFlight(false), hasPendingPkt(false)
 {
 }
 
@@ -182,6 +182,7 @@ LSQUnit<Impl>::init(O3CPU *cpu_ptr, IEW *iew_ptr, DerivO3CPUParams *params,
     memDepViolator = NULL;
 
     blockedLoadSeqNum = 0;
+    needsTSO = params->needsTSO;
 }
 
 template<class Impl>
@@ -770,6 +771,7 @@ LSQUnit<Impl>::writebackStores()
            storeWBIdx != storeTail &&
            storeQueue[storeWBIdx].inst &&
            storeQueue[storeWBIdx].canWB &&
+           ((!needsTSO) || (!storeInFlight)) &&
            usedPorts < cachePorts) {
 
         if (isStoreBlocked || lsq->cacheBlocked()) {
@@ -1090,6 +1092,10 @@ LSQUnit<Impl>::storePostSend(PacketPtr pkt)
 #endif
     }
 
+    if (needsTSO) {
+        storeInFlight = true;
+    }
+
     incrStIdx(storeWBIdx);
 }
 
@@ -1163,6 +1169,10 @@ LSQUnit<Impl>::completeStore(int store_idx)
 
     storeQueue[store_idx].inst->setCompleted();
 
+    if (needsTSO) {
+        storeInFlight = false;
+    }
+
     // Tell the checker we've completed this instruction.  Some stores
     // may get reported twice to the checker, but the checker can
     // handle that case.