/*
 * Copyright (c) 2011-2012 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 <list>

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

/**
 * This typedef is used to clean up getAddrRanges(). It's declared
 * outside the Port object since it's also used by some mem objects.
 * Eventually we should move this typedef to wherever Addr is
 * defined.
 */

typedef std::list<AddrRange> AddrRangeList;
typedef std::list<AddrRange>::iterator AddrRangeIter;
typedef std::list<AddrRange>::const_iterator AddrRangeConstIter;

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 recvRetry 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 recvRetry 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.
     */
    virtual void sendRetry();

    /**
     * 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 or
     * sendTimingSnoopResp was called on this master port (causing
     * recvTimingReq and recvTimingSnoopResp to be called on the
     * slave port) and was unsuccesful.
     */
    virtual void recvRetry() = 0;

    /**
     * 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 recvRetry 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 or sendTimingSnoopResp to this slave port and
     * failed.
     */
    void sendRetry();

    /**
     * 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 recvRetry() = 0;

};

#endif //__MEM_PORT_HH__
