Fix a bug to handle the fact that a CPU can send Functional accesses while a sendTimi...
[gem5.git] / src / mem / port.hh
index 1b1920c037c7eb7d2407d42448d3b32d06dabf9c..75afc04e623b810a7ac9d6ec8d9e9b46a3325dfb 100644 (file)
  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * Authors: Ron Dreslinski
  */
 
 /**
  * @file
- * Port Object Decleration. Ports are used to interface memory objects to
+ * Port Object Declaration. Ports are used to interface memory objects to
  * each other.  They will always come in pairs, and we refer to the other
  * port object as the peer.  These are used to make the design more
  * modular so that a specific interface between every type of objcet doesn't
@@ -56,6 +58,8 @@
 typedef std::list<Range<Addr> > AddrRangeList;
 typedef std::list<Range<Addr> >::iterator AddrRangeIter;
 
+class MemObject;
+
 /**
  * Ports are used to interface memory objects to
  * each other.  They will always come in pairs, and we refer to the other
@@ -69,36 +73,63 @@ typedef std::list<Range<Addr> >::iterator AddrRangeIter;
  */
 class Port
 {
+  private:
+
+    /** Descriptive name (for DPRINTF output) */
+    mutable std::string portName;
+
+    /** A pointer to the peer port.  Ports always come in pairs, that way they
+        can use a standardized interface to communicate between different
+        memory objects. */
+    Port *peer;
+
+    /** A pointer to the MemObject that owns this port. This may not be set. */
+    MemObject *owner;
+
   public:
 
+    Port()
+        : peer(NULL), owner(NULL)
+    { }
+
+    /**
+     * Constructor.
+     *
+     * @param _name Port name for DPRINTF output.  Should include name
+     * of memory system object to which the port belongs.
+     * @param _owner Pointer to the MemObject that owns this port.
+     * Will not necessarily be set.
+     */
+    Port(const std::string &_name, MemObject *_owner = NULL)
+        : portName(_name), peer(NULL), owner(_owner)
+    { }
+
+    /** Return port name (for DPRINTF). */
+    const std::string &name() const { return portName; }
+
     virtual ~Port() {};
+
     // mey be better to use subclasses & RTTI?
-    /** Holds the ports status.  Keeps track if it is blocked, or has
-        calculated a range change. */
+    /** Holds the ports status.  Currently just that a range recomputation needs
+     * to be done. */
     enum Status {
-        Blocked,
-        Unblocked,
         RangeChange
     };
 
-  private:
+    void setName(const std::string &name)
+    { portName = name; }
 
-    /** A pointer to the peer port.  Ports always come in pairs, that way they
-        can use a standardized interface to communicate between different
-        memory objects. */
-    Port *peer;
+    /** Function to set the pointer for the peer port. */
+    void setPeer(Port *port);
 
-  public:
+    /** Function to get the pointer to the peer port. */
+    Port *getPeer() { return peer; }
 
-    /** Function to set the pointer for the peer port.
-        @todo should be called by the configuration stuff (python).
-    */
-    void setPeer(Port *port) { peer = port; }
+    /** Function to set the owner of this port. */
+    void setOwner(MemObject *_owner) { owner = _owner; }
 
-        /** Function to set the pointer for the peer port.
-        @todo should be called by the configuration stuff (python).
-    */
-    Port *getPeer() { return peer; }
+    /** Function to return the owner of this port. */
+    MemObject *getOwner() { return owner; }
 
   protected:
 
@@ -106,13 +137,13 @@ class Port
      * called by a peer port, never directly by any outside object. */
 
     /** Called to recive a timing call from the peer port. */
-    virtual bool recvTiming(Packet *pkt) = 0;
+    virtual bool recvTiming(PacketPtr pkt) = 0;
 
     /** Called to recive a atomic call from the peer port. */
-    virtual Tick recvAtomic(Packet *pkt) = 0;
+    virtual Tick recvAtomic(PacketPtr pkt) = 0;
 
     /** Called to recive a functional call from the peer port. */
-    virtual void recvFunctional(Packet *pkt) = 0;
+    virtual void recvFunctional(PacketPtr pkt) = 0;
 
     /** Called to recieve a status change from the peer port. */
     virtual void recvStatusChange(Status status) = 0;
@@ -121,7 +152,7 @@ class Port
         wait.  This shouldn't be valid for response paths (IO Devices).
         so it is set to panic if it isn't already defined.
     */
-    virtual Packet *recvRetry() { panic("??"); }
+    virtual void recvRetry() { panic("??"); }
 
     /** Called by a peer port in order to determine the block size of the
         device connected to this port.  It sometimes doesn't make sense for
@@ -146,17 +177,18 @@ class Port
         port receive function.
         @return This function returns if the send was succesful in it's
         recieve. If it was a failure, then the port will wait for a recvRetry
-        at which point it can issue a successful sendTiming.  This is used in
+        at which point it can possibly issue a successful sendTiming.  This is used in
         case a cache has a higher priority request come in while waiting for
         the bus to arbitrate.
     */
-    bool sendTiming(Packet *pkt) { return peer->recvTiming(pkt); }
+    bool sendTiming(PacketPtr pkt) { return peer->recvTiming(pkt); }
 
-    /** Function called by the associated device to send an atomic access,
-        an access in which the data is moved and the state is updated in one
-        cycle, without interleaving with other memory accesses.
-    */
-    Tick sendAtomic(Packet *pkt)
+    /** Function called by the associated device to send an atomic
+     *   access, an access in which the data is moved and the state is
+     *   updated in one cycle, without interleaving with other memory
+     *   accesses.  Returns estimated latency of access.
+     */
+    Tick sendAtomic(PacketPtr pkt)
         { return peer->recvAtomic(pkt); }
 
     /** Function called by the associated device to send a functional access,
@@ -164,7 +196,7 @@ class Port
         memory system, without affecting the current state of any block or
         moving the block.
     */
-    void sendFunctional(Packet *pkt)
+    void sendFunctional(PacketPtr pkt)
         { return peer->recvFunctional(pkt); }
 
     /** Called by the associated device to send a status change to the device
@@ -175,7 +207,7 @@ class Port
     /** When a timing access doesn't return a success, some time later the
         Retry will be sent.
     */
-    Packet *sendRetry() { return peer->recvRetry(); }
+    void sendRetry() { return peer->recvRetry(); }
 
     /** Called by the associated device if it wishes to find out the blocksize
         of the device on attached to the peer port.
@@ -213,7 +245,7 @@ class Port
 
     /** Internal helper function for read/writeBlob().
      */
-    void blobHelper(Addr addr, uint8_t *p, int size, Command cmd);
+    void blobHelper(Addr addr, uint8_t *p, int size, Packet::Command cmd);
 };
 
 /** A simple functional port that is only meant for one way communication to
@@ -224,11 +256,25 @@ class Port
 class FunctionalPort : public Port
 {
   public:
-    virtual bool recvTiming(Packet *pkt) { panic("FuncPort is UniDir"); }
-    virtual Tick recvAtomic(Packet *pkt) { panic("FuncPort is UniDir"); }
-    virtual void recvFunctional(Packet *pkt) { panic("FuncPort is UniDir"); }
+    FunctionalPort(const std::string &_name, MemObject *_owner = NULL)
+        : Port(_name, _owner)
+    {}
+
+  protected:
+    virtual bool recvTiming(PacketPtr pkt) { panic("FuncPort is UniDir"); }
+    virtual Tick recvAtomic(PacketPtr pkt) { panic("FuncPort is UniDir"); }
+    virtual void recvFunctional(PacketPtr pkt) { panic("FuncPort is UniDir"); }
     virtual void recvStatusChange(Status status) {}
 
+  public:
+    /** a write function that also does an endian conversion. */
+    template <typename T>
+    inline void writeHtoG(Addr addr, T d);
+
+    /** a read function that also does an endian conversion. */
+    template <typename T>
+    inline T readGtoH(Addr addr);
+
     template <typename T>
     inline void write(Addr addr, T d)
     {