merge: style.py fix
[gem5.git] / src / cpu / ozone / lw_lsq.hh
index b2924db54f5912b9c8d490eba5e3e11ca7cd8e38..ba40e9ce1c459e59d012d148ab3f5cb100b10074 100644 (file)
@@ -37,7 +37,7 @@
 #include <algorithm>
 
 #include "arch/faults.hh"
-#include "arch/isa_traits.hh"
+#include "arch/types.hh"
 #include "config/full_system.hh"
 #include "base/hashmap.hh"
 #include "cpu/inst_seq.hh"
@@ -47,7 +47,7 @@
 #include "sim/debug.hh"
 #include "sim/sim_object.hh"
 
-//class PageTable;
+class MemObject;
 
 /**
  * Class that implements the actual LQ and SQ for each specific thread.
@@ -64,7 +64,7 @@ template <class Impl>
 class OzoneLWLSQ {
   public:
     typedef typename Impl::Params Params;
-    typedef typename Impl::FullCPU FullCPU;
+    typedef typename Impl::OzoneCPU OzoneCPU;
     typedef typename Impl::BackEnd BackEnd;
     typedef typename Impl::DynInstPtr DynInstPtr;
     typedef typename Impl::IssueStruct IssueStruct;
@@ -73,35 +73,6 @@ class OzoneLWLSQ {
 
     typedef typename std::map<InstSeqNum, DynInstPtr>::iterator LdMapIt;
 
-  private:
-    class StoreCompletionEvent : public Event {
-      public:
-        /** Constructs a store completion event. */
-        StoreCompletionEvent(DynInstPtr &inst, BackEnd *be,
-                             Event *wb_event, OzoneLWLSQ *lsq_ptr);
-
-        /** Processes the store completion event. */
-        void process();
-
-        /** Returns the description of this event. */
-        const char *description();
-
-      private:
-        /** The store index of the store being written back. */
-        DynInstPtr inst;
-
-        BackEnd *be;
-        /** The writeback event for the store.  Needed for store
-         * conditionals.
-         */
-      public:
-        Event *wbEvent;
-        bool miss;
-      private:
-        /** The pointer to the LSQ unit that issued the store. */
-        OzoneLWLSQ<Impl> *lsqPtr;
-    };
-
   public:
     /** Constructs an LSQ unit. init() must be called prior to use. */
     OzoneLWLSQ();
@@ -113,16 +84,16 @@ class OzoneLWLSQ {
     /** Returns the name of the LSQ unit. */
     std::string name() const;
 
+    void regStats();
+
     /** Sets the CPU pointer. */
-    void setCPU(FullCPU *cpu_ptr)
-    { cpu = cpu_ptr; }
+    void setCPU(OzoneCPU *cpu_ptr);
 
     /** Sets the back-end stage pointer. */
     void setBE(BackEnd *be_ptr)
     { be = be_ptr; }
 
-    /** Sets the page table pointer. */
-//    void setPageTable(PageTable *pt_ptr);
+    Port *getDcachePort() { return &dcachePort; }
 
     /** Ticks the LSQ unit, which in this case only resets the number of
      * used cache ports.
@@ -155,6 +126,10 @@ class OzoneLWLSQ {
     /** Writes back stores. */
     void writebackStores();
 
+    /** Completes the data access that has been returned from the
+     * memory system. */
+    void completeDataAccess(PacketPtr pkt);
+
     // @todo: Include stats in the LSQ unit.
     //void regStats();
 
@@ -206,7 +181,7 @@ class OzoneLWLSQ {
     int numLoads() { return loads; }
 
     /** Returns the number of stores in the SQ. */
-    int numStores() { return stores; }
+    int numStores() { return stores + storesInFlight; }
 
     /** Returns if either the LQ or SQ is full. */
     bool isFull() { return lqFull() || sqFull(); }
@@ -215,7 +190,7 @@ class OzoneLWLSQ {
     bool lqFull() { return loads >= (LQEntries - 1); }
 
     /** Returns if the SQ is full. */
-    bool sqFull() { return stores >= (SQEntries - 1); }
+    bool sqFull() { return (stores + storesInFlight) >= (SQEntries - 1); }
 
     /** Debugging function to dump instructions in the LSQ. */
     void dumpInsts();
@@ -231,8 +206,8 @@ class OzoneLWLSQ {
 
     /** Returns if the LSQ unit will writeback on this cycle. */
     bool willWB() { return storeQueue.back().canWB &&
-                        !storeQueue.back().completed/* &&
-                                                       !dcacheInterface->isBlocked()*/; }
+                        !storeQueue.back().completed &&
+                        !isStoreBlocked; }
 
     void switchOut();
 
@@ -243,26 +218,35 @@ class OzoneLWLSQ {
     bool switchedOut;
 
   private:
+    /** Writes back the instruction, sending it to IEW. */
+    void writeback(DynInstPtr &inst, PacketPtr pkt);
+
+    /** Handles completing the send of a store to memory. */
+    void storePostSend(PacketPtr pkt, DynInstPtr &inst);
+
     /** Completes the store at the specified index. */
-    void completeStore(int store_idx);
+    void completeStore(DynInstPtr &inst);
+
+    void removeStore(int store_idx);
+
+    /** Handles doing the retry. */
+    void recvRetry();
 
   private:
     /** Pointer to the CPU. */
-    FullCPU *cpu;
+    OzoneCPU *cpu;
 
     /** Pointer to the back-end stage. */
     BackEnd *be;
 
-    MemObject *mem;
-
     class DcachePort : public Port
     {
       protected:
-        FullCPU *cpu;
+        OzoneLWLSQ *lsq;
 
       public:
-        DcachePort(const std::string &_name, FullCPU *_cpu)
-            : Port(_name), cpu(_cpu)
+        DcachePort(OzoneLWLSQ *_lsq)
+            : lsq(_lsq)
         { }
 
       protected:
@@ -273,20 +257,17 @@ class OzoneLWLSQ {
         virtual void recvStatusChange(Status status);
 
         virtual void getDeviceAddressRanges(AddrRangeList &resp,
-                                            AddrRangeList &snoop)
-        { resp.clear(); snoop.clear(); }
+                                            bool &snoop)
+        { resp.clear(); snoop = true; }
 
         virtual bool recvTiming(PacketPtr pkt);
 
         virtual void recvRetry();
     };
 
-    /** Pointer to the D-cache. */
+    /** D-cache port. */
     DcachePort dcachePort;
 
-    /** Pointer to the page table. */
-//    PageTable *pTable;
-
   public:
     struct SQEntry {
         /** Constructs an empty store queue entry. */
@@ -319,6 +300,48 @@ class OzoneLWLSQ {
         typename std::list<DynInstPtr>::iterator lqIt;
     };
 
+    /** Derived class to hold any sender state the LSQ needs. */
+    class LSQSenderState : public Packet::SenderState
+    {
+      public:
+        /** Default constructor. */
+        LSQSenderState()
+            : noWB(false)
+        { }
+
+        /** Instruction who initiated the access to memory. */
+        DynInstPtr inst;
+        /** Whether or not it is a load. */
+        bool isLoad;
+        /** The LQ/SQ index of the instruction. */
+        int idx;
+        /** Whether or not the instruction will need to writeback. */
+        bool noWB;
+    };
+
+    /** Writeback event, specifically for when stores forward data to loads. */
+    class WritebackEvent : public Event {
+      public:
+        /** Constructs a writeback event. */
+        WritebackEvent(DynInstPtr &_inst, PacketPtr pkt, OzoneLWLSQ *lsq_ptr);
+
+        /** Processes the writeback event. */
+        void process();
+
+        /** Returns the description of this event. */
+        const char *description();
+
+      private:
+        /** Instruction whose results are being written back. */
+        DynInstPtr inst;
+
+        /** The packet that would have been sent to memory. */
+        PacketPtr pkt;
+
+        /** The pointer to the LSQ unit that issued the store. */
+        OzoneLWLSQ<Impl> *lsqPtr;
+    };
+
     enum Status {
         Running,
         Idle,
@@ -373,6 +396,10 @@ class OzoneLWLSQ {
 
     int storesToWB;
 
+  public:
+    int storesInFlight;
+
+  private:
     /// @todo Consider moving to a more advanced model with write vs read ports
     /** The number of cache ports available each cycle. */
     int cachePorts;
@@ -382,6 +409,9 @@ class OzoneLWLSQ {
 
     //list<InstSeqNum> mshrSeqNums;
 
+    /** Tota number of memory ordering violations. */
+    Stats::Scalar<> lsqMemOrderViolation;
+
      //Stats::Scalar<> dcacheStallCycles;
     Counter lastDcacheStall;
 
@@ -395,6 +425,12 @@ class OzoneLWLSQ {
     /** The index of the above store. */
     LQIt stallingLoad;
 
+    /** The packet that needs to be retried. */
+    PacketPtr retryPkt;
+
+    /** Whehter or not a store is blocked due to the memory system. */
+    bool isStoreBlocked;
+
     /** Whether or not a load is blocked due to the memory system.  It is
      *  cleared when this value is checked via loadBlocked().
      */
@@ -469,8 +505,8 @@ OzoneLWLSQ<Impl>::read(RequestPtr req, T &data, int load_idx)
     // at the head of the LSQ and are ready to commit (at the head of the ROB
     // too).
     // @todo: Fix uncached accesses.
-    if (req->getFlags() & UNCACHEABLE &&
-        (inst != loadQueue.back() || !inst->reachedCommit)) {
+    if (req->isUncacheable() &&
+        (inst != loadQueue.back() || !inst->isAtCommit())) {
         DPRINTF(OzoneLSQ, "[sn:%lli] Uncached load and not head of "
                 "commit/LSQ!\n",
                 inst->seqNum);
@@ -498,7 +534,7 @@ OzoneLWLSQ<Impl>::read(RequestPtr req, T &data, int load_idx)
 
         store_size = (*sq_it).size;
 
-        if (store_size == 0) {
+        if (store_size == 0 || (*sq_it).committed) {
             sq_it++;
             continue;
         }
@@ -532,17 +568,19 @@ OzoneLWLSQ<Impl>::read(RequestPtr req, T &data, int load_idx)
 
             DPRINTF(OzoneLSQ, "Forwarding from store [sn:%lli] to load to "
                     "[sn:%lli] addr %#x, data %#x\n",
-                    (*sq_it).inst->seqNum, inst->seqNum, req->vaddr, *(inst->memData));
-/*
-            typename BackEnd::LdWritebackEvent *wb =
-                new typename BackEnd::LdWritebackEvent(inst,
-                                                       be);
+                    (*sq_it).inst->seqNum, inst->seqNum, req->getVaddr(),
+                    *(inst->memData));
+
+            PacketPtr data_pkt = new Packet(req, Packet::ReadReq, Packet::Broadcast);
+            data_pkt->dataStatic(inst->memData);
+
+            WritebackEvent *wb = new WritebackEvent(inst, data_pkt, this);
 
             // We'll say this has a 1 cycle load-store forwarding latency
             // for now.
-            // FIXME - Need to make this a parameter.
+            // @todo: Need to make this a parameter.
             wb->schedule(curTick);
-*/
+
             // Should keep track of stat for forwarded data
             return NoFault;
         } else if ((store_has_lower_limit && lower_load_has_store_part) ||
@@ -575,7 +613,7 @@ OzoneLWLSQ<Impl>::read(RequestPtr req, T &data, int load_idx)
 
             DPRINTF(OzoneLSQ, "Load-store forwarding mis-match. "
                     "Store [sn:%lli] to load addr %#x\n",
-                    (*sq_it).inst->seqNum, req->vaddr);
+                    (*sq_it).inst->seqNum, req->getVaddr());
 
             return NoFault;
         }
@@ -594,9 +632,19 @@ OzoneLWLSQ<Impl>::read(RequestPtr req, T &data, int load_idx)
     DPRINTF(OzoneLSQ, "Doing timing access for inst PC %#x\n",
             inst->readPC());
 
-    PacketPtr data_pkt = new Packet(req, Packet::ReadReq, Packet::Broadcast);
+    PacketPtr data_pkt =
+        new Packet(req,
+                   (req->isLocked() ?
+                    MemCmd::LoadLockedReq : Packet::ReadReq),
+                   Packet::Broadcast);
     data_pkt->dataStatic(inst->memData);
 
+    LSQSenderState *state = new LSQSenderState;
+    state->isLoad = true;
+    state->idx = load_idx;
+    state->inst = inst;
+    data_pkt->senderState = state;
+
     // if we have a cache, do cache access too
     if (!dcachePort.sendTiming(data_pkt)) {
         // There's an older load that's already going to squash.
@@ -613,14 +661,8 @@ OzoneLWLSQ<Impl>::read(RequestPtr req, T &data, int load_idx)
         return NoFault;
     }
 
-    if (data_pkt->result != Packet::Success) {
-        DPRINTF(OzoneLSQ, "OzoneLSQ: D-cache miss!\n");
-        DPRINTF(Activity, "Activity: ld accessing mem miss [sn:%lli]\n",
-                inst->seqNum);
-    } else {
-        DPRINTF(OzoneLSQ, "OzoneLSQ: D-cache hit!\n");
-        DPRINTF(Activity, "Activity: ld accessing mem hit [sn:%lli]\n",
-                inst->seqNum);
+    if (req->isLocked()) {
+        cpu->lockFlag = true;
     }
 
     return NoFault;