mem: Fix guest corruption when caches handle uncacheable accesses
[gem5.git] / src / mem / simple_mem.hh
index 5f136ed51b9d1d5f640053fd9677a8697f02ecfc..ab002f2702f7fc7af24f51692f0fb0be27ade462 100644 (file)
 #include "params/SimpleMemory.hh"
 
 /**
- * The simple memory is a basic multi-ported memory with an infinite
- * throughput and a fixed latency, potentially with a variance added
- * to it. It uses a SimpleTimingPort to implement the timing accesses.
+ * The simple memory is a basic single-ported memory controller with
+ * an configurable throughput and latency, potentially with a variance
+ * added to the latter. It uses a QueueSlavePort to avoid dealing with
+ * the flow control of sending responses.
+ * @sa  \ref gem5MemorySystem "gem5 Memory System"
  */
 class SimpleMemory : public AbstractMemory
 {
 
   private:
 
-    class MemoryPort : public SimpleTimingPort
+    class MemoryPort : public QueuedSlavePort
     {
+
+      private:
+
+        /// Queue holding the response packets
+        SlavePacketQueue queueImpl;
         SimpleMemory& memory;
 
       public:
@@ -73,41 +80,67 @@ class SimpleMemory : public AbstractMemory
 
       protected:
 
-        virtual Tick recvAtomic(PacketPtr pkt);
+        Tick recvAtomic(PacketPtr pkt);
+
+        void recvFunctional(PacketPtr pkt);
 
-        virtual void recvFunctional(PacketPtr pkt);
+        bool recvTimingReq(PacketPtr pkt);
 
-        virtual AddrRangeList getAddrRanges() const;
+        AddrRangeList getAddrRanges() const;
 
     };
 
-    std::vector<MemoryPort*> ports;
+    MemoryPort port;
 
     Tick lat;
     Tick lat_var;
 
+    /// Bandwidth in ticks per byte
+    const double bandwidth;
+
+    /**
+     * Track the state of the memory as either idle or busy, no need
+     * for an enum with only two states.
+     */
+    bool isBusy;
+
+    /**
+     * Remember if we have to retry an outstanding request that
+     * arrived while we were busy.
+     */
+    bool retryReq;
+
+    /**
+     * Release the memory after being busy and send a retry if a
+     * request was rejected in the meanwhile.
+     */
+    void release();
+
+    EventWrapper<SimpleMemory, &SimpleMemory::release> releaseEvent;
+
+    /** @todo this is a temporary workaround until the 4-phase code is
+     * committed. upstream caches needs this packet until true is returned, so
+     * hold onto it for deletion until a subsequent call
+     */
+    std::vector<PacketPtr> pendingDelete;
+
   public:
 
-    typedef SimpleMemoryParams Params;
-    SimpleMemory(const Params *p);
+    SimpleMemory(const SimpleMemoryParams *p);
     virtual ~SimpleMemory() { }
 
-    unsigned int drain(Event* de);
+    unsigned int drain(DrainManager *dm);
 
-    virtual SlavePort& getSlavePort(const std::string& if_name, int idx = -1);
+    virtual BaseSlavePort& getSlavePort(const std::string& if_name,
+                                        PortID idx = InvalidPortID);
     virtual void init();
 
-    const Params *
-    params() const
-    {
-        return dynamic_cast<const Params *>(_params);
-    }
-
   protected:
 
     Tick doAtomicAccess(PacketPtr pkt);
     void doFunctionalAccess(PacketPtr pkt);
-    virtual Tick calculateLatency(PacketPtr pkt);
+    bool recvTimingReq(PacketPtr pkt);
+    Tick calculateLatency(PacketPtr pkt);
 
 };