add microPC stuff back in. got deleted on changeset propragation somehow.
[gem5.git] / src / cpu / o3 / lsq_unit_impl.hh
index ebd9301f6ecc505fb5a9e2d8bb5f016104257de1..71b416c9c92141922618e657f870d0698ea48f07 100644 (file)
@@ -57,6 +57,11 @@ LSQUnit<Impl>::WritebackEvent::process()
     if (!lsqPtr->isSwitchedOut()) {
         lsqPtr->writeback(inst, pkt);
     }
+
+    if (pkt->senderState)
+        delete pkt->senderState;
+
+    delete pkt->req;
     delete pkt;
 }
 
@@ -64,7 +69,7 @@ template<class Impl>
 const char *
 LSQUnit<Impl>::WritebackEvent::description()
 {
-    return "Store writeback event";
+    return "Store writeback";
 }
 
 template<class Impl>
@@ -78,11 +83,10 @@ LSQUnit<Impl>::completeDataAccess(PacketPtr pkt)
 
     //iewStage->ldstQueue.removeMSHR(inst->threadNumber,inst->seqNum);
 
+    assert(!pkt->wasNacked());
+
     if (isSwitchedOut() || inst->isSquashed()) {
         iewStage->decrWb(inst->seqNum);
-        delete state;
-        delete pkt;
-        return;
     } else {
         if (!state->noWB) {
             writeback(inst, pkt);
@@ -94,6 +98,7 @@ LSQUnit<Impl>::completeDataAccess(PacketPtr pkt)
     }
 
     delete state;
+    delete pkt->req;
     delete pkt;
 }
 
@@ -107,9 +112,12 @@ LSQUnit<Impl>::LSQUnit()
 
 template<class Impl>
 void
-LSQUnit<Impl>::init(Params *params, LSQ *lsq_ptr, unsigned maxLQEntries,
-                    unsigned maxSQEntries, unsigned id)
+LSQUnit<Impl>::init(O3CPU *cpu_ptr, IEW *iew_ptr, Params *params, LSQ *lsq_ptr,
+                    unsigned maxLQEntries, unsigned maxSQEntries, unsigned id)
 {
+    cpu = cpu_ptr;
+    iewStage = iew_ptr;
+
     DPRINTF(LSQUnit, "Creating LSQUnit%i object.\n",id);
 
     switchedOut = false;
@@ -138,19 +146,6 @@ LSQUnit<Impl>::init(Params *params, LSQ *lsq_ptr, unsigned maxLQEntries,
     blockedLoadSeqNum = 0;
 }
 
-template<class Impl>
-void
-LSQUnit<Impl>::setCPU(O3CPU *cpu_ptr)
-{
-    cpu = cpu_ptr;
-
-#if USE_CHECKER
-    if (cpu->checker) {
-        cpu->checker->setDcachePort(dcachePort);
-    }
-#endif
-}
-
 template<class Impl>
 std::string
 LSQUnit<Impl>::name() const
@@ -207,6 +202,19 @@ LSQUnit<Impl>::regStats()
         .desc("Number of times an access to memory failed due to the cache being blocked");
 }
 
+template<class Impl>
+void
+LSQUnit<Impl>::setDcachePort(Port *dcache_port)
+{
+    dcachePort = dcache_port;
+
+#if USE_CHECKER
+    if (cpu->checker) {
+        cpu->checker->setDcachePort(dcachePort);
+    }
+#endif
+}
+
 template<class Impl>
 void
 LSQUnit<Impl>::clearLQ()
@@ -403,12 +411,15 @@ template <class Impl>
 Fault
 LSQUnit<Impl>::executeLoad(DynInstPtr &inst)
 {
+    using namespace TheISA;
     // Execute a specific load.
     Fault load_fault = NoFault;
 
     DPRINTF(LSQUnit, "Executing load PC %#x, [sn:%lli]\n",
             inst->readPC(),inst->seqNum);
 
+    assert(!inst->isSquashed());
+
     load_fault = inst->initiateAcc();
 
     // If the instruction faulted, then we need to send it along to commit
@@ -418,12 +429,44 @@ LSQUnit<Impl>::executeLoad(DynInstPtr &inst)
         // realizes there is activity.
         // Mark it as executed unless it is an uncached load that
         // needs to hit the head of commit.
-        if (!(inst->req && inst->req->isUncacheable()) ||
+        if (!(inst->hasRequest() && inst->uncacheable()) ||
             inst->isAtCommit()) {
             inst->setExecuted();
         }
         iewStage->instToCommit(inst);
         iewStage->activityThisCycle();
+    } else if (!loadBlocked()) {
+        assert(inst->effAddrValid);
+        int load_idx = inst->lqIdx;
+        incrLdIdx(load_idx);
+        while (load_idx != loadTail) {
+            // Really only need to check loads that have actually executed
+
+            // @todo: For now this is extra conservative, detecting a
+            // violation if the addresses match assuming all accesses
+            // are quad word accesses.
+
+            // @todo: Fix this, magic number being used here
+            if (loadQueue[load_idx]->effAddrValid &&
+                (loadQueue[load_idx]->effAddr >> 8) ==
+                (inst->effAddr >> 8)) {
+                // A load incorrectly passed this load.  Squash and refetch.
+                // For now return a fault to show that it was unsuccessful.
+                DynInstPtr violator = loadQueue[load_idx];
+                if (!memDepViolator ||
+                    (violator->seqNum < memDepViolator->seqNum)) {
+                    memDepViolator = violator;
+                } else {
+                    break;
+                }
+
+                ++lsqMemOrderViolation;
+
+                return genMachineCheckFault();
+            }
+
+            incrLdIdx(load_idx);
+        }
     }
 
     return load_fault;
@@ -442,6 +485,8 @@ LSQUnit<Impl>::executeStore(DynInstPtr &store_inst)
     DPRINTF(LSQUnit, "Executing store PC %#x [sn:%lli]\n",
             store_inst->readPC(), store_inst->seqNum);
 
+    assert(!store_inst->isSquashed());
+
     // Check the recently completed loads to see if any match this store's
     // address.  If so, then we have a memory ordering violation.
     int load_idx = store_inst->lqIdx;
@@ -465,32 +510,36 @@ LSQUnit<Impl>::executeStore(DynInstPtr &store_inst)
         ++storesToWB;
     }
 
-    if (!memDepViolator) {
-        while (load_idx != loadTail) {
-            // Really only need to check loads that have actually executed
-            // It's safe to check all loads because effAddr is set to
-            // InvalAddr when the dyn inst is created.
-
-            // @todo: For now this is extra conservative, detecting a
-            // violation if the addresses match assuming all accesses
-            // are quad word accesses.
-
-            // @todo: Fix this, magic number being used here
-            if ((loadQueue[load_idx]->effAddr >> 8) ==
-                (store_inst->effAddr >> 8)) {
-                // A load incorrectly passed this store.  Squash and refetch.
-                // For now return a fault to show that it was unsuccessful.
-                memDepViolator = loadQueue[load_idx];
-                ++lsqMemOrderViolation;
-
-                return genMachineCheckFault();
+    assert(store_inst->effAddrValid);
+    while (load_idx != loadTail) {
+        // Really only need to check loads that have actually executed
+        // It's safe to check all loads because effAddr is set to
+        // InvalAddr when the dyn inst is created.
+
+        // @todo: For now this is extra conservative, detecting a
+        // violation if the addresses match assuming all accesses
+        // are quad word accesses.
+
+        // @todo: Fix this, magic number being used here
+        if (loadQueue[load_idx]->effAddrValid &&
+            (loadQueue[load_idx]->effAddr >> 8) ==
+            (store_inst->effAddr >> 8)) {
+            // A load incorrectly passed this store.  Squash and refetch.
+            // For now return a fault to show that it was unsuccessful.
+            DynInstPtr violator = loadQueue[load_idx];
+            if (!memDepViolator ||
+                (violator->seqNum < memDepViolator->seqNum)) {
+                memDepViolator = violator;
+            } else {
+                break;
             }
 
-            incrLdIdx(load_idx);
+            ++lsqMemOrderViolation;
+
+            return genMachineCheckFault();
         }
 
-        // If we've reached this point, there was no violation.
-        memDepViolator = NULL;
+        incrLdIdx(load_idx);
     }
 
     return store_fault;
@@ -598,22 +647,13 @@ LSQUnit<Impl>::writebackStores()
         assert(!inst->memData);
         inst->memData = new uint8_t[64];
 
-        TheISA::IntReg convertedData =
-            TheISA::htog(storeQueue[storeWBIdx].data);
-
-        //FIXME This is a hack to get SPARC working. It, along with endianness
-        //in the memory system in general, need to be straightened out more
-        //formally. The problem is that the data's endianness is swapped when
-        //it's in the 64 bit data field in the store queue. The data that you
-        //want won't start at the beginning of the field anymore unless it was
-        //a 64 bit access.
-        memcpy(inst->memData,
-                (uint8_t *)&convertedData +
-                (TheISA::ByteOrderDiffers ?
-                 (sizeof(TheISA::IntReg) - req->getSize()) : 0),
-                req->getSize());
-
-        PacketPtr data_pkt = new Packet(req, Packet::WriteReq, Packet::Broadcast);
+        memcpy(inst->memData, storeQueue[storeWBIdx].data, req->getSize());
+
+        MemCmd command =
+            req->isSwap() ? MemCmd::SwapReq :
+            (req->isLocked() ? MemCmd::StoreCondReq : MemCmd::WriteReq);
+        PacketPtr data_pkt = new Packet(req, command,
+                                        Packet::Broadcast);
         data_pkt->dataStatic(inst->memData);
 
         LSQSenderState *state = new LSQSenderState;
@@ -629,7 +669,7 @@ LSQUnit<Impl>::writebackStores()
                 inst->seqNum);
 
         // @todo: Remove this SC hack once the memory system handles it.
-        if (req->isLocked()) {
+        if (inst->isStoreConditional()) {
             // Disable recording the result temporarily.  Writing to
             // misc regs normally updates the result, but this is not
             // the desired behavior when handling store conditionals.
@@ -644,7 +684,6 @@ LSQUnit<Impl>::writebackStores()
                         inst->seqNum);
                 WritebackEvent *wb = new WritebackEvent(inst, data_pkt, this);
                 wb->schedule(curTick + 1);
-                delete state;
                 completeStore(storeWBIdx);
                 incrStIdx(storeWBIdx);
                 continue;
@@ -655,11 +694,8 @@ LSQUnit<Impl>::writebackStores()
         }
 
         if (!dcachePort->sendTiming(data_pkt)) {
-            if (data_pkt->result == Packet::BadAddress) {
-                panic("LSQ sent out a bad address for a completed store!");
-            }
             // Need to handle becoming blocked on a store.
-            DPRINTF(IEW, "D-Cache became blcoked when writing [sn:%lli], will"
+            DPRINTF(IEW, "D-Cache became blocked when writing [sn:%lli], will"
                     "retry later\n",
                     inst->seqNum);
             isStoreBlocked = true;
@@ -734,6 +770,10 @@ LSQUnit<Impl>::squash(const InstSeqNum &squashed_num)
         }
     }
 
+    if (memDepViolator && squashed_num < memDepViolator->seqNum) {
+        memDepViolator = NULL;
+    }
+
     int store_idx = storeTail;
     decrStIdx(store_idx);
 
@@ -763,6 +803,11 @@ LSQUnit<Impl>::squash(const InstSeqNum &squashed_num)
         storeQueue[store_idx].inst = NULL;
         storeQueue[store_idx].canWB = 0;
 
+        // Must delete request now that it wasn't handed off to
+        // memory.  This is quite ugly.  @todo: Figure out the proper
+        // place to really handle request deletes.
+        delete storeQueue[store_idx].req;
+
         storeQueue[store_idx].req = NULL;
         --stores;
 
@@ -800,26 +845,6 @@ LSQUnit<Impl>::storePostSend(PacketPtr pkt)
 #endif
     }
 
-    if (pkt->result != Packet::Success) {
-        DPRINTF(LSQUnit,"D-Cache Write Miss on idx:%i!\n",
-                storeWBIdx);
-
-        DPRINTF(Activity, "Active st accessing mem miss [sn:%lli]\n",
-                storeQueue[storeWBIdx].inst->seqNum);
-
-        //mshrSeqNums.push_back(storeQueue[storeWBIdx].inst->seqNum);
-
-        //DPRINTF(LSQUnit, "Added MSHR. count = %i\n",mshrSeqNums.size());
-
-        // @todo: Increment stat here.
-    } else {
-        DPRINTF(LSQUnit,"D-Cache: Write Hit on idx:%i !\n",
-                storeWBIdx);
-
-        DPRINTF(Activity, "Active st accessing mem hit [sn:%lli]\n",
-                storeQueue[storeWBIdx].inst->seqNum);
-    }
-
     incrStIdx(storeWBIdx);
 }
 
@@ -905,12 +930,10 @@ void
 LSQUnit<Impl>::recvRetry()
 {
     if (isStoreBlocked) {
+        DPRINTF(LSQUnit, "Receiving retry: store blocked\n");
         assert(retryPkt != NULL);
 
         if (dcachePort->sendTiming(retryPkt)) {
-            if (retryPkt->result == Packet::BadAddress) {
-                panic("LSQ sent out a bad address for a completed store!");
-            }
             storePostSend(retryPkt);
             retryPkt = NULL;
             isStoreBlocked = false;