/*
 * Copyright (c) 2011-2012,2015 ARM Limited
 * All rights reserved
 *
 * The license below extends only to copyright in the software and shall
 * not be construed as granting a license to any other intellectual
 * property including but not limited to intellectual property relating
 * to a hardware implementation of the functionality of the software
 * licensed hereunder.  You may use the software subject to the license
 * terms below provided that you ensure that this notice is replicated
 * unmodified and in its entirety in all distributions of the software,
 * modified or unmodified, in source code or in binary form.
 *
 * Copyright (c) 2002-2005 The Regents of The University of Michigan
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are
 * met: redistributions of source code must retain the above copyright
 * notice, this list of conditions and the following disclaimer;
 * redistributions in binary form must reproduce the above copyright
 * notice, this list of conditions and the following disclaimer in the
 * documentation and/or other materials provided with the distribution;
 * neither the name of the copyright holders nor the names of its
 * contributors may be used to endorse or promote products derived from
 * this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
 * 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
 *          Andreas Hansson
 *          William Wang
 */

/**
 * @file
 * Port Object Declaration.
 */

#ifndef __MEM_PORT_HH__
#define __MEM_PORT_HH__

#include "base/addr_range.hh"
#include "mem/packet.hh"

class MemObject;

/**
 * Ports are used to interface memory objects to each other. A port is
 * either a master or a slave and the connected peer is always of the
 * opposite role. Each port has a name, an owner, and an identifier.
 */
class Port
{

  private:

    /** Descriptive name (for DPRINTF output) */
    std::string portName;

  protected:

    /**
     * A numeric identifier to distinguish ports in a vector, and set
     * to InvalidPortID in case this port is not part of a vector.
     */
    const PortID id;

    /** A reference to the MemObject that owns this port. */
    MemObject& owner;

    /**
     * Abstract base class for ports
     *
     * @param _name Port name including the owners name
     * @param _owner The MemObject that is the structural owner of this port
     * @param _id A port identifier for vector ports
     */
    Port(const std::string& _name, MemObject& _owner, PortID _id);

    /**
     * Virtual destructor due to inheritance.
     */
    virtual ~Port();

  public:

    /** Return port name (for DPRINTF). */
    const std::string name() const { return portName; }

    /** Get the port id. */
    PortID getId() const { return id; }

};

/** Forward declaration */
class BaseSlavePort;

/**
 * A BaseMasterPort is a protocol-agnostic master port, responsible
 * only for the structural connection to a slave port. The final
 * master port that inherits from the base class must override the
 * bind member function for the specific slave port class.
 */
class BaseMasterPort : public Port
{

  protected:

    BaseSlavePort* _baseSlavePort;

    BaseMasterPort(const std::string& name, MemObject* owner,
                   PortID id = InvalidPortID);
    virtual ~BaseMasterPort();

  public:

    virtual void bind(BaseSlavePort& slave_port) = 0;
    virtual void unbind() = 0;
    BaseSlavePort& getSlavePort() const;
    bool isConnected() const;

};

/**
 * A BaseSlavePort is a protocol-agnostic slave port, responsible
 * only for the structural connection to a master port.
 */
class BaseSlavePort : public Port
{

  protected:

    BaseMasterPort* _baseMasterPort;

    BaseSlavePort(const std::string& name, MemObject* owner,
                  PortID id = InvalidPortID);
    virtual ~BaseSlavePort();

  public:

    BaseMasterPort& getMasterPort() const;
    bool isConnected() const;

};

/** Forward declaration */
class SlavePort;

/**
 * A MasterPort is a specialisation of a BaseMasterPort, which
 * implements the default protocol for the three different level of
 * transport functions. In addition to the basic functionality of
 * sending packets, it also has functions to receive range changes or
 * determine if the port is snooping or not.
 */
class MasterPort : public BaseMasterPort
{

    friend class SlavePort;

  private:

    SlavePort* _slavePort;

  public:

    MasterPort(const std::string& name, MemObject* owner,
               PortID id = InvalidPortID);
    virtual ~MasterPort();

    /**
     * Bind this master port to a slave port. This also does the
     * mirror action and binds the slave port to the master port.
     */
    void bind(BaseSlavePort& slave_port);

    /**
     * Unbind this master port and the associated slave port.
     */
    void unbind();

    /**
     * Send an atomic request packet, where the data is moved and the
     * state is updated in zero time, without interleaving with other
     * memory accesses.
     *
     * @param pkt Packet to send.
     *
     * @return Estimated latency of access.
     */
    Tick sendAtomic(PacketPtr pkt);

    /**
     * Send a functional request packet, where the data is instantly
     * updated everywhere in the memory system, without affecting the
     * current state of any block or moving the block.
     *
     * @param pkt Packet to send.
     */
    void sendFunctional(PacketPtr pkt);

    /**
     * Attempt to send a timing request to the slave port by calling
     * its corresponding receive function. If the send does not
     * succeed, as indicated by the return value, then the sender must
     * wait for a recvReqRetry at which point it can re-issue a
     * sendTimingReq.
     *
     * @param pkt Packet to send.
     *
     * @return If the send was succesful or not.
    */
    bool sendTimingReq(PacketPtr pkt);

    /**
     * Attempt to send a timing snoop response packet to the slave
     * port by calling its corresponding receive function. If the send
     * does not succeed, as indicated by the return value, then the
     * sender must wait for a recvRetrySnoop at which point it can
     * re-issue a sendTimingSnoopResp.
     *
     * @param pkt Packet to send.
     */
    bool sendTimingSnoopResp(PacketPtr pkt);

    /**
     * Send a retry to the slave port that previously attempted a
     * sendTimingResp to this master port and failed. Note that this
     * is virtual so that the "fake" snoop response port in the
     * coherent crossbar can override the behaviour.
     */
    virtual void sendRetryResp();

    /**
     * Determine if this master port is snooping or not. The default
     * implementation returns false and thus tells the neighbour we
     * are not snooping. Any master port that wants to receive snoop
     * requests (e.g. a cache connected to a bus) has to override this
     * function.
     *
     * @return true if the port should be considered a snooper
     */
    virtual bool isSnooping() const { return false; }

    /**
     * Get the address ranges of the connected slave port.
     */
    AddrRangeList getAddrRanges() const;

    /** Inject a PrintReq for the given address to print the state of
     * that address throughout the memory system.  For debugging.
     */
    void printAddr(Addr a);

  protected:

    /**
     * Receive an atomic snoop request packet from the slave port.
     */
    virtual Tick recvAtomicSnoop(PacketPtr pkt)
    {
        panic("%s was not expecting an atomic snoop request\n", name());
        return 0;
    }

    /**
     * Receive a functional snoop request packet from the slave port.
     */
    virtual void recvFunctionalSnoop(PacketPtr pkt)
    {
        panic("%s was not expecting a functional snoop request\n", name());
    }

    /**
     * Receive a timing response from the slave port.
     */
    virtual bool recvTimingResp(PacketPtr pkt) = 0;

    /**
     * Receive a timing snoop request from the slave port.
     */
    virtual void recvTimingSnoopReq(PacketPtr pkt)
    {
        panic("%s was not expecting a timing snoop request\n", name());
    }

    /**
     * Called by the slave port if sendTimingReq was called on this
     * master port (causing recvTimingReq to be called on the slave
     * port) and was unsuccesful.
     */
    virtual void recvReqRetry() = 0;

    /**
     * Called by the slave port if sendTimingSnoopResp was called on this
     * master port (causing recvTimingSnoopResp to be called on the slave
     * port) and was unsuccesful.
     */
    virtual void recvRetrySnoopResp()
    {
        panic("%s was not expecting a snoop retry\n", name());
    }

    /**
     * Called to receive an address range change from the peer slave
     * port. The default implementation ignores the change and does
     * nothing. Override this function in a derived class if the owner
     * needs to be aware of the address ranges, e.g. in an
     * interconnect component like a bus.
     */
    virtual void recvRangeChange() { }
};

/**
 * A SlavePort is a specialisation of a port. In addition to the
 * basic functionality of sending packets to its master peer, it also
 * has functions specific to a slave, e.g. to send range changes
 * and get the address ranges that the port responds to.
 */
class SlavePort : public BaseSlavePort
{

    friend class MasterPort;

  private:

    MasterPort* _masterPort;

  public:

    SlavePort(const std::string& name, MemObject* owner,
              PortID id = InvalidPortID);
    virtual ~SlavePort();

    /**
     * Send an atomic snoop request packet, where the data is moved
     * and the state is updated in zero time, without interleaving
     * with other memory accesses.
     *
     * @param pkt Snoop packet to send.
     *
     * @return Estimated latency of access.
     */
    Tick sendAtomicSnoop(PacketPtr pkt);

    /**
     * Send a functional snoop request packet, where the data is
     * instantly updated everywhere in the memory system, without
     * affecting the current state of any block or moving the block.
     *
     * @param pkt Snoop packet to send.
     */
    void sendFunctionalSnoop(PacketPtr pkt);

    /**
     * Attempt to send a timing response to the master port by calling
     * its corresponding receive function. If the send does not
     * succeed, as indicated by the return value, then the sender must
     * wait for a recvRespRetry at which point it can re-issue a
     * sendTimingResp.
     *
     * @param pkt Packet to send.
     *
     * @return If the send was succesful or not.
    */
    bool sendTimingResp(PacketPtr pkt);

    /**
     * Attempt to send a timing snoop request packet to the master port
     * by calling its corresponding receive function. Snoop requests
     * always succeed and hence no return value is needed.
     *
     * @param pkt Packet to send.
     */
    void sendTimingSnoopReq(PacketPtr pkt);

    /**
     * Send a retry to the master port that previously attempted a
     * sendTimingReq to this slave port and failed.
     */
    void sendRetryReq();

    /**
     * Send a retry to the master port that previously attempted a
     * sendTimingSnoopResp to this slave port and failed.
     */
    void sendRetrySnoopResp();

    /**
     * Find out if the peer master port is snooping or not.
     *
     * @return true if the peer master port is snooping
     */
    bool isSnooping() const { return _masterPort->isSnooping(); }

    /**
     * Called by the owner to send a range change
     */
    void sendRangeChange() const {
        if (!_masterPort)
            fatal("%s cannot sendRangeChange() without master port", name());
        _masterPort->recvRangeChange();
    }

    /**
     * Get a list of the non-overlapping address ranges the owner is
     * responsible for. All slave ports must override this function
     * and return a populated list with at least one item.
     *
     * @return a list of ranges responded to
     */
    virtual AddrRangeList getAddrRanges() const = 0;

  protected:

    /**
     * Called by the master port to unbind. Should never be called
     * directly.
     */
    void unbind();

    /**
     * Called by the master port to bind. Should never be called
     * directly.
     */
    void bind(MasterPort& master_port);

    /**
     * Receive an atomic request packet from the master port.
     */
    virtual Tick recvAtomic(PacketPtr pkt) = 0;

    /**
     * Receive a functional request packet from the master port.
     */
    virtual void recvFunctional(PacketPtr pkt) = 0;

    /**
     * Receive a timing request from the master port.
     */
    virtual bool recvTimingReq(PacketPtr pkt) = 0;

    /**
     * Receive a timing snoop response from the master port.
     */
    virtual bool recvTimingSnoopResp(PacketPtr pkt)
    {
        panic("%s was not expecting a timing snoop response\n", name());
    }

    /**
     * Called by the master port if sendTimingResp was called on this
     * slave port (causing recvTimingResp to be called on the master
     * port) and was unsuccesful.
     */
    virtual void recvRespRetry() = 0;

};

#endif //__MEM_PORT_HH__
