SLICC: Remove WakeUp* import calls from ast/__init__.py
[gem5.git] / src / mem / physical.hh
index 50fa75ed3e865ec9803faab421419ab6fc3ae21b..cd6d809e240dd9a6c265b4cc3ee38dec1cb4e7dc 100644 (file)
 #ifndef __PHYSICAL_MEMORY_HH__
 #define __PHYSICAL_MEMORY_HH__
 
+#include <map>
+#include <string>
+
 #include "base/range.hh"
 #include "mem/mem_object.hh"
 #include "mem/packet.hh"
-#include "mem/port.hh"
+#include "mem/tport.hh"
+#include "params/PhysicalMemory.hh"
 #include "sim/eventq.hh"
-#include <map>
-#include <string>
 
 //
 // Functional model for a contiguous block of physical memory. (i.e. RAM)
 //
 class PhysicalMemory : public MemObject
 {
-    class MemoryPort : public Port
+  protected:
+
+    class MemoryPort : public SimpleTimingPort
     {
         PhysicalMemory *memory;
 
@@ -57,67 +61,126 @@ class PhysicalMemory : public MemObject
 
       protected:
 
-        virtual bool recvTiming(Packet *pkt);
-
-        virtual Tick recvAtomic(Packet *pkt);
+        virtual Tick recvAtomic(PacketPtr pkt);
 
-        virtual void recvFunctional(Packet *pkt);
+        virtual void recvFunctional(PacketPtr pkt);
 
         virtual void recvStatusChange(Status status);
 
         virtual void getDeviceAddressRanges(AddrRangeList &resp,
-                                            AddrRangeList &snoop);
+                                            bool &snoop);
 
-        virtual int deviceBlockSize();
+        virtual unsigned deviceBlockSize() const;
     };
 
     int numPorts;
 
 
-    struct MemResponseEvent : public Event
-    {
-        Packet *pkt;
-        MemoryPort *memoryPort;
-
-        MemResponseEvent(Packet *pkt, MemoryPort *memoryPort);
-        void process();
-        const char *description();
-    };
-
   private:
     // prevent copying of a MainMemory object
     PhysicalMemory(const PhysicalMemory &specmem);
     const PhysicalMemory &operator=(const PhysicalMemory &specmem);
 
   protected:
-    Addr base_addr;
-    Addr pmem_size;
-    uint8_t *pmem_addr;
-    MemoryPort *port;
-    int page_ptr;
+
+    class LockedAddr {
+      public:
+        // on alpha, minimum LL/SC granularity is 16 bytes, so lower
+        // bits need to masked off.
+        static const Addr Addr_Mask = 0xf;
+
+        static Addr mask(Addr paddr) { return (paddr & ~Addr_Mask); }
+
+        Addr addr;      // locked address
+        int contextId;     // locking hw context
+
+        // check for matching execution context
+        bool matchesContext(Request *req)
+        {
+            return (contextId == req->contextId());
+        }
+
+        LockedAddr(Request *req)
+            : addr(mask(req->getPaddr())),
+              contextId(req->contextId())
+        {
+        }
+        // constructor for unserialization use
+        LockedAddr(Addr _addr, int _cid)
+            : addr(_addr), contextId(_cid)
+        {
+        }
+    };
+
+    std::list<LockedAddr> lockedAddrList;
+
+    // helper function for checkLockedAddrs(): we really want to
+    // inline a quick check for an empty locked addr list (hopefully
+    // the common case), and do the full list search (if necessary) in
+    // this out-of-line function
+    bool checkLockedAddrList(PacketPtr pkt);
+
+    // Record the address of a load-locked operation so that we can
+    // clear the execution context's lock flag if a matching store is
+    // performed
+    void trackLoadLocked(PacketPtr pkt);
+
+    // Compare a store address with any locked addresses so we can
+    // clear the lock flag appropriately.  Return value set to 'false'
+    // if store operation should be suppressed (because it was a
+    // conditional store and the address was no longer locked by the
+    // requesting execution context), 'true' otherwise.  Note that
+    // this method must be called on *all* stores since even
+    // non-conditional stores must clear any matching lock addresses.
+    bool writeOK(PacketPtr pkt) {
+        Request *req = pkt->req;
+        if (lockedAddrList.empty()) {
+            // no locked addrs: nothing to check, store_conditional fails
+            bool isLLSC = pkt->isLLSC();
+            if (isLLSC) {
+                req->setExtraData(0);
+            }
+            return !isLLSC; // only do write if not an sc
+        } else {
+            // iterate over list...
+            return checkLockedAddrList(pkt);
+        }
+    }
+
+    uint8_t *pmemAddr;
     Tick lat;
+    Tick lat_var;
+    std::vector<MemoryPort*> ports;
+    typedef std::vector<MemoryPort*>::iterator PortIterator;
 
+    uint64_t _size;
+    uint64_t _start;
   public:
-    Addr new_page();
-    uint64_t size() { return pmem_size; }
+    uint64_t size() { return _size; }
+    uint64_t start() { return _start; }
 
   public:
-    PhysicalMemory(const std::string &n, Tick latency);
+    typedef PhysicalMemoryParams Params;
+    PhysicalMemory(const Params *p);
     virtual ~PhysicalMemory();
 
+    const Params *
+    params() const
+    {
+        return dynamic_cast<const Params *>(_params);
+    }
+
   public:
-    int deviceBlockSize();
-    void getAddressRanges(AddrRangeList &resp, AddrRangeList &snoop);
+    unsigned deviceBlockSize() const;
+    void getAddressRanges(AddrRangeList &resp, bool &snoop);
     virtual Port *getPort(const std::string &if_name, int idx = -1);
     void virtual init();
+    unsigned int drain(Event *de);
 
-    // fast back-door memory access for vtophys(), remote gdb, etc.
-    // uint64_t phys_read_qword(Addr addr) const;
-  private:
-    bool doTimingAccess(Packet *pkt, MemoryPort *memoryPort);
-    Tick doAtomicAccess(Packet *pkt);
-    void doFunctionalAccess(Packet *pkt);
-
+  protected:
+    Tick doAtomicAccess(PacketPtr pkt);
+    void doFunctionalAccess(PacketPtr pkt);
+    virtual Tick calculateLatency(PacketPtr pkt);
     void recvStatusChange(Port::Status status);
 
   public: