Move Dcache port creation from LSQUnit to LSQ in order to support Ron's recent change...
authorKevin Lim <ktlim@umich.edu>
Thu, 13 Jul 2006 17:12:51 +0000 (13:12 -0400)
committerKevin Lim <ktlim@umich.edu>
Thu, 13 Jul 2006 17:12:51 +0000 (13:12 -0400)
src/cpu/o3/lsq.hh:
    Update to have LSQ work with only one dcache port for all LSQ Units.  LSQ has the dcache port, and the LSQ Units must tell the LSQ if the cache has become blocked.
src/cpu/o3/lsq_impl.hh:
    Updates to have the LSQ work with only one dcache port for all LSQUnits.
src/cpu/o3/lsq_unit.hh:
src/cpu/o3/lsq_unit_impl.hh:
    Update for LSQ to create dcache port instead of LSQUnits.  Now LSQUnits are given the dcache port from the LSQ, and also must check the LSQ if the cache is blocked prior to accessing the cache.

--HG--
extra : convert_revision : 2708adbf323f4e7647dc0c1e31ef5bb4596b89f8

src/cpu/o3/lsq.hh
src/cpu/o3/lsq_impl.hh
src/cpu/o3/lsq_unit.hh
src/cpu/o3/lsq_unit_impl.hh

index d5890950f0ca22905fb4b9ac21523f2b99f98490..190734dc2acdf38211c97dbc87a28024b56db6b1 100644 (file)
@@ -70,7 +70,7 @@ class LSQ {
      *  to work.  For now it just returns the port from one of the
      *  threads.
      */
-    Port *getDcachePort() { return thread[0].getDcachePort(); }
+    Port *getDcachePort() { return &dcachePort; }
 
     /** Sets the pointer to the list of active threads. */
     void setActiveThreads(std::list<unsigned> *at_ptr);
@@ -258,6 +258,15 @@ class LSQ {
     bool willWB(unsigned tid)
     { return thread[tid].willWB(); }
 
+    /** Returns if the cache is currently blocked. */
+    bool cacheBlocked()
+    { return retryTid != -1; }
+
+    /** Sets the retry thread id, indicating that one of the LSQUnits
+     * tried to access the cache but the cache was blocked. */
+    void setRetryTid(int tid)
+    { retryTid = tid; }
+
     /** Debugging function to print out all instructions. */
     void dumpInsts();
     /** Debugging function to print out instructions from a specific thread. */
@@ -274,7 +283,49 @@ class LSQ {
     template <class T>
     Fault write(RequestPtr req, T &data, int store_idx);
 
-  private:
+    /** DcachePort class for this LSQ.  Handles doing the
+     * communication with the cache/memory.
+     */
+    class DcachePort : public Port
+    {
+      protected:
+        /** Pointer to LSQ. */
+        LSQ *lsq;
+
+      public:
+        /** Default constructor. */
+        DcachePort(LSQ *_lsq)
+            : lsq(_lsq)
+        { }
+
+      protected:
+        /** Atomic version of receive.  Panics. */
+        virtual Tick recvAtomic(PacketPtr pkt);
+
+        /** Functional version of receive.  Panics. */
+        virtual void recvFunctional(PacketPtr pkt);
+
+        /** Receives status change.  Other than range changing, panics. */
+        virtual void recvStatusChange(Status status);
+
+        /** Returns the address ranges of this device. */
+        virtual void getDeviceAddressRanges(AddrRangeList &resp,
+                                            AddrRangeList &snoop)
+        { resp.clear(); snoop.clear(); }
+
+        /** Timing version of receive.  Handles writing back and
+         * completing the load or store that has returned from
+         * memory. */
+        virtual bool recvTiming(PacketPtr pkt);
+
+        /** Handles doing a retry of the previous send. */
+        virtual void recvRetry();
+    };
+
+    /** D-cache port. */
+    DcachePort dcachePort;
+
+  protected:
     /** The LSQ policy for SMT mode. */
     LSQPolicy lsqPolicy;
 
@@ -303,6 +354,10 @@ class LSQ {
 
     /** Number of Threads. */
     unsigned numThreads;
+
+    /** The thread id of the LSQ Unit that is currently waiting for a
+     * retry. */
+    int retryTid;
 };
 
 template <class Impl>
index 89fd1a71da8fb9fa25358f90c7db9f8c37462ae5..4e3957029881fa16c703ab65a8f1602076b35530 100644 (file)
 
 using namespace std;
 
+template <class Impl>
+Tick
+LSQ<Impl>::DcachePort::recvAtomic(PacketPtr pkt)
+{
+    panic("O3CPU model does not work with atomic mode!");
+    return curTick;
+}
+
+template <class Impl>
+void
+LSQ<Impl>::DcachePort::recvFunctional(PacketPtr pkt)
+{
+    panic("O3CPU doesn't expect recvFunctional callback!");
+}
+
+template <class Impl>
+void
+LSQ<Impl>::DcachePort::recvStatusChange(Status status)
+{
+    if (status == RangeChange)
+        return;
+
+    panic("O3CPU doesn't expect recvStatusChange callback!");
+}
+
+template <class Impl>
+bool
+LSQ<Impl>::DcachePort::recvTiming(PacketPtr pkt)
+{
+    lsq->thread[pkt->req->getThreadNum()].completeDataAccess(pkt);
+    return true;
+}
+
+template <class Impl>
+void
+LSQ<Impl>::DcachePort::recvRetry()
+{
+    lsq->thread[lsq->retryTid].recvRetry();
+    // Speculatively clear the retry Tid.  This will get set again if
+    // the LSQUnit was unable to complete its access.
+    lsq->retryTid = -1;
+}
+
 template <class Impl>
 LSQ<Impl>::LSQ(Params *params)
-    : LQEntries(params->LQEntries), SQEntries(params->SQEntries),
-      numThreads(params->numberOfThreads)
+    : dcachePort(this), LQEntries(params->LQEntries),
+      SQEntries(params->SQEntries), numThreads(params->numberOfThreads),
+      retryTid(-1)
 {
     DPRINTF(LSQ, "Creating LSQ object.\n");
 
@@ -94,7 +138,8 @@ LSQ<Impl>::LSQ(Params *params)
 
     //Initialize LSQs
     for (int tid=0; tid < numThreads; tid++) {
-        thread[tid].init(params, maxLQEntries, maxSQEntries, tid);
+        thread[tid].init(params, this, maxLQEntries, maxSQEntries, tid);
+        thread[tid].setDcachePort(&dcachePort);
     }
 }
 
@@ -130,6 +175,8 @@ LSQ<Impl>::setCPU(O3CPU *cpu_ptr)
 {
     cpu = cpu_ptr;
 
+    dcachePort.setName(name());
+
     for (int tid=0; tid < numThreads; tid++) {
         thread[tid].setCPU(cpu_ptr);
     }
index 4d7a8350b6ef8fd5f9e64dd520bac93f849deddf..a76a73f0c552086992faa5ae46e48e3a181c3028 100644 (file)
@@ -64,6 +64,7 @@ class LSQUnit {
     typedef typename Impl::O3CPU O3CPU;
     typedef typename Impl::DynInstPtr DynInstPtr;
     typedef typename Impl::CPUPol::IEW IEW;
+    typedef typename Impl::CPUPol::LSQ LSQ;
     typedef typename Impl::CPUPol::IssueStruct IssueStruct;
 
   public:
@@ -71,17 +72,12 @@ class LSQUnit {
     LSQUnit();
 
     /** Initializes the LSQ unit with the specified number of entries. */
-    void init(Params *params, unsigned maxLQEntries,
+    void init(Params *params, LSQ *lsq_ptr, unsigned maxLQEntries,
               unsigned maxSQEntries, unsigned id);
 
     /** Returns the name of the LSQ unit. */
     std::string name() const;
 
-    /** Returns the dcache port.
-     *  @todo: Remove this once the port moves up to the LSQ level.
-     */
-    Port *getDcachePort() { return dcachePort; }
-
     /** Registers statistics. */
     void regStats();
 
@@ -92,6 +88,10 @@ class LSQUnit {
     void setIEW(IEW *iew_ptr)
     { iewStage = iew_ptr; }
 
+    /** Sets the pointer to the dcache port. */
+    void setDcachePort(Port *dcache_port)
+    { dcachePort = dcache_port; }
+
     /** Switches out LSQ unit. */
     void switchOut();
 
@@ -211,6 +211,9 @@ class LSQUnit {
                         !storeQueue[storeWBIdx].completed &&
                         !isStoreBlocked; }
 
+    /** Handles doing the retry. */
+    void recvRetry();
+
   private:
     /** Writes back the instruction, sending it to IEW. */
     void writeback(DynInstPtr &inst, PacketPtr pkt);
@@ -221,9 +224,6 @@ class LSQUnit {
     /** Completes the store at the specified index. */
     void completeStore(int store_idx);
 
-    /** Handles doing the retry. */
-    void recvRetry();
-
     /** Increments the given store index (circular queue). */
     inline void incrStIdx(int &store_idx);
     /** Decrements the given store index (circular queue). */
@@ -244,54 +244,11 @@ class LSQUnit {
     /** Pointer to the IEW stage. */
     IEW *iewStage;
 
-    /** Pointer to memory object. */
-    MemObject *mem;
+    /** Pointer to the LSQ. */
+    LSQ *lsq;
 
-    /** DcachePort class for this LSQ Unit.  Handles doing the
-     * communication with the cache/memory.
-     * @todo: Needs to be moved to the LSQ level and have some sort
-     * of arbitration.
-     */
-    class DcachePort : public Port
-    {
-      protected:
-        /** Pointer to CPU. */
-        O3CPU *cpu;
-        /** Pointer to LSQ. */
-        LSQUnit *lsq;
-
-      public:
-        /** Default constructor. */
-        DcachePort(O3CPU *_cpu, LSQUnit *_lsq)
-            : Port(_lsq->name() + "-dport"), cpu(_cpu), lsq(_lsq)
-        { }
-
-      protected:
-        /** Atomic version of receive.  Panics. */
-        virtual Tick recvAtomic(PacketPtr pkt);
-
-        /** Functional version of receive.  Panics. */
-        virtual void recvFunctional(PacketPtr pkt);
-
-        /** Receives status change.  Other than range changing, panics. */
-        virtual void recvStatusChange(Status status);
-
-        /** Returns the address ranges of this device. */
-        virtual void getDeviceAddressRanges(AddrRangeList &resp,
-                                            AddrRangeList &snoop)
-        { resp.clear(); snoop.clear(); }
-
-        /** Timing version of receive.  Handles writing back and
-         * completing the load or store that has returned from
-         * memory. */
-        virtual bool recvTiming(PacketPtr pkt);
-
-        /** Handles doing a retry of the previous send. */
-        virtual void recvRetry();
-    };
-
-    /** Pointer to the D-cache. */
-    DcachePort *dcachePort;
+    /** Pointer to the dcache port.  Used only for sending. */
+    Port *dcachePort;
 
     /** Derived class to hold any sender state the LSQ needs. */
     class LSQSenderState : public Packet::SenderState
@@ -658,7 +615,7 @@ LSQUnit<Impl>::read(Request *req, T &data, int load_idx)
     }
 
     // If there's no forwarding case, then go access memory
-    DPRINTF(LSQUnit, "Doing functional access for inst [sn:%lli] PC %#x\n",
+    DPRINTF(LSQUnit, "Doing memory access for inst [sn:%lli] PC %#x\n",
             load_inst->seqNum, load_inst->readPC());
 
     assert(!load_inst->memData);
@@ -666,9 +623,6 @@ LSQUnit<Impl>::read(Request *req, T &data, int load_idx)
 
     ++usedPorts;
 
-    DPRINTF(LSQUnit, "Doing timing access for inst PC %#x\n",
-            load_inst->readPC());
-
     PacketPtr data_pkt = new Packet(req, Packet::ReadReq, Packet::Broadcast);
     data_pkt->dataStatic(load_inst->memData);
 
@@ -678,8 +632,18 @@ LSQUnit<Impl>::read(Request *req, T &data, int load_idx)
     state->inst = load_inst;
     data_pkt->senderState = state;
 
-    // if we have a cache, do cache access too
-    if (!dcachePort->sendTiming(data_pkt)) {
+    // if we the cache is not blocked, do cache access
+    if (!lsq->cacheBlocked()) {
+        if (!dcachePort->sendTiming(data_pkt)) {
+            // If the access didn't succeed, tell the LSQ by setting
+            // the retry thread id.
+            lsq->setRetryTid(lsqID);
+        }
+    }
+
+    // If the cache was blocked, or has become blocked due to the access,
+    // handle it.
+    if (lsq->cacheBlocked()) {
         ++lsqCacheBlocked;
         // There's an older load that's already going to squash.
         if (isLoadBlocked && blockedLoadSeqNum < load_inst->seqNum)
index 8e951534f227238a0c4e9775053ec248dc3bb5a7..85b150cd97ec8f4e0fe73a08b67fd0bd5dc88ec4 100644 (file)
@@ -31,6 +31,7 @@
 
 #include "config/use_checker.hh"
 
+#include "cpu/o3/lsq.hh"
 #include "cpu/o3/lsq_unit.hh"
 #include "base/str.hh"
 #include "mem/packet.hh"
@@ -95,46 +96,6 @@ LSQUnit<Impl>::completeDataAccess(PacketPtr pkt)
     delete pkt;
 }
 
-template <class Impl>
-Tick
-LSQUnit<Impl>::DcachePort::recvAtomic(PacketPtr pkt)
-{
-    panic("O3CPU model does not work with atomic mode!");
-    return curTick;
-}
-
-template <class Impl>
-void
-LSQUnit<Impl>::DcachePort::recvFunctional(PacketPtr pkt)
-{
-    panic("O3CPU doesn't expect recvFunctional callback!");
-}
-
-template <class Impl>
-void
-LSQUnit<Impl>::DcachePort::recvStatusChange(Status status)
-{
-    if (status == RangeChange)
-        return;
-
-    panic("O3CPU doesn't expect recvStatusChange callback!");
-}
-
-template <class Impl>
-bool
-LSQUnit<Impl>::DcachePort::recvTiming(PacketPtr pkt)
-{
-    lsq->completeDataAccess(pkt);
-    return true;
-}
-
-template <class Impl>
-void
-LSQUnit<Impl>::DcachePort::recvRetry()
-{
-    lsq->recvRetry();
-}
-
 template <class Impl>
 LSQUnit<Impl>::LSQUnit()
     : loads(0), stores(0), storesToWB(0), stalled(false),
@@ -145,13 +106,15 @@ LSQUnit<Impl>::LSQUnit()
 
 template<class Impl>
 void
-LSQUnit<Impl>::init(Params *params, unsigned maxLQEntries,
+LSQUnit<Impl>::init(Params *params, LSQ *lsq_ptr, unsigned maxLQEntries,
                     unsigned maxSQEntries, unsigned id)
 {
     DPRINTF(LSQUnit, "Creating LSQUnit%i object.\n",id);
 
     switchedOut = false;
 
+    lsq = lsq_ptr;
+
     lsqID = id;
 
     // Add 1 for the sentinel entry (they are circular queues).
@@ -168,8 +131,6 @@ LSQUnit<Impl>::init(Params *params, unsigned maxLQEntries,
     usedPorts = 0;
     cachePorts = params->cachePorts;
 
-    mem = params->mem;
-
     memDepViolator = NULL;
 
     blockedLoadSeqNum = 0;
@@ -180,7 +141,6 @@ void
 LSQUnit<Impl>::setCPU(O3CPU *cpu_ptr)
 {
     cpu = cpu_ptr;
-    dcachePort = new DcachePort(cpu, this);
 
 #if USE_CHECKER
     if (cpu->checker) {
@@ -588,7 +548,7 @@ LSQUnit<Impl>::writebackStores()
            storeQueue[storeWBIdx].canWB &&
            usedPorts < cachePorts) {
 
-        if (isStoreBlocked) {
+        if (isStoreBlocked || lsq->cacheBlocked()) {
             DPRINTF(LSQUnit, "Unable to write back any more stores, cache"
                     " is blocked!\n");
             break;
@@ -911,6 +871,7 @@ LSQUnit<Impl>::recvRetry()
         } else {
             // Still blocked!
             ++lsqCacheBlocked;
+            lsq->setRetryTid(lsqID);
         }
     } else if (isLoadBlocked) {
         DPRINTF(LSQUnit, "Loads squash themselves and all younger insts, "