/*
- * Copyright (c) 2012 ARM Limited
+ * Copyright (c) 2012-2013 ARM Limited
* All rights reserved
*
* The license below extends only to copyright in the software and shall
* SimpleMemory declaration
*/
-#ifndef __SIMPLE_MEMORY_HH__
-#define __SIMPLE_MEMORY_HH__
+#ifndef __MEM_SIMPLE_MEMORY_HH__
+#define __MEM_SIMPLE_MEMORY_HH__
+
+#include <list>
#include "mem/abstract_mem.hh"
-#include "mem/tport.hh"
+#include "mem/port.hh"
#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
+ * a configurable throughput and latency.
+ *
+ * @sa \ref gem5MemorySystem "gem5 Memory System"
*/
class SimpleMemory : public AbstractMemory
{
private:
- class MemoryPort : public SimpleTimingPort
+ /**
+ * A deferred packet stores a packet along with its scheduled
+ * transmission time
+ */
+ class DeferredPacket
+ {
+
+ public:
+
+ const Tick tick;
+ const PacketPtr pkt;
+
+ DeferredPacket(PacketPtr _pkt, Tick _tick) : tick(_tick), pkt(_pkt)
+ { }
+ };
+
+ class MemoryPort : public SlavePort
{
+
+ private:
+
SimpleMemory& memory;
public:
protected:
- virtual Tick recvAtomic(PacketPtr pkt);
+ Tick recvAtomic(PacketPtr pkt);
- virtual void recvFunctional(PacketPtr pkt);
+ void recvFunctional(PacketPtr pkt);
- virtual AddrRangeList getAddrRanges() const;
+ bool recvTimingReq(PacketPtr pkt);
- };
+ void recvRespRetry();
- std::vector<MemoryPort*> ports;
+ AddrRangeList getAddrRanges() const;
- Tick lat;
- Tick lat_var;
+ };
+
+ MemoryPort port;
+
+ /**
+ * Latency from that a request is accepted until the response is
+ * ready to be sent.
+ */
+ const Tick latency;
+
+ /**
+ * Fudge factor added to the latency.
+ */
+ const Tick latency_var;
+
+ /**
+ * Internal (unbounded) storage to mimic the delay caused by the
+ * actual memory access. Note that this is where the packet spends
+ * the memory latency.
+ */
+ std::list<DeferredPacket> packetQueue;
+
+ /**
+ * Bandwidth in ticks per byte. The regulation affects the
+ * acceptance rate of requests and the queueing takes place after
+ * the regulation.
+ */
+ 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;
+
+ /**
+ * Remember if we failed to send a response and are awaiting a
+ * retry. This is only used as a check.
+ */
+ bool retryResp;
+
+ /**
+ * Release the memory after being busy and send a retry if a
+ * request was rejected in the meanwhile.
+ */
+ void release();
+
+ EventFunctionWrapper releaseEvent;
+
+ /**
+ * Dequeue a packet from our internal packet queue and move it to
+ * the port where it will be sent as soon as possible.
+ */
+ void dequeue();
+
+ EventFunctionWrapper dequeueEvent;
+
+ /**
+ * Detemine the latency.
+ *
+ * @return the latency seen by the current packet
+ */
+ Tick getLatency() const;
+
+ /**
+ * Upstream caches need this packet until true is returned, so
+ * hold it for deletion until a subsequent call
+ */
+ std::unique_ptr<Packet> pendingDelete;
public:
- typedef SimpleMemoryParams Params;
- SimpleMemory(const Params *p);
- virtual ~SimpleMemory() { }
+ SimpleMemory(const SimpleMemoryParams *p);
- unsigned int drain(Event* de);
+ DrainState drain() override;
- virtual SlavePort& getSlavePort(const std::string& if_name, int idx = -1);
- virtual void init();
-
- const Params *
- params() const
- {
- return dynamic_cast<const Params *>(_params);
- }
+ BaseSlavePort& getSlavePort(const std::string& if_name,
+ PortID idx = InvalidPortID) override;
+ void init() override;
protected:
- Tick doAtomicAccess(PacketPtr pkt);
- void doFunctionalAccess(PacketPtr pkt);
- virtual Tick calculateLatency(PacketPtr pkt);
+ Tick recvAtomic(PacketPtr pkt);
+
+ void recvFunctional(PacketPtr pkt);
+
+ bool recvTimingReq(PacketPtr pkt);
+
+ void recvRespRetry();
};
-#endif //__SIMPLE_MEMORY_HH__
+#endif //__MEM_SIMPLE_MEMORY_HH__