/*
 * Copyright (c) 2018-2020 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.
 *
 * 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.
 *
 * Author: Matteo Andreozzi
 */


#ifndef __MEM_QOS_MEM_SINK_HH__
#define __MEM_QOS_MEM_SINK_HH__

#include "mem/abstract_mem.hh"
#include "mem/qos/mem_ctrl.hh"
#include "mem/qport.hh"
#include "params/QoSMemSinkCtrl.hh"

class QoSMemSinkInterfaceParams;
class QoSMemSinkInterface;

namespace QoS {

/**
 * QoS Memory Sink
 *
 * The QoS Memory Sink is a lightweight memory controller with QoS
 * support. It is meant to provide a QoS aware simple memory system
 * without the need of using a complex DRAM memory controller
 */
class MemSinkCtrl : public MemCtrl
{
  protected:
    /**
     * The Request packets are store in a multiple dequeue structure,
     * based on their QoS priority
     */
    using PacketQueue = std::deque<PacketPtr>;

  private:
    class MemoryPort : public QueuedResponsePort
    {
      private:
        /** reference to parent memory object */
        MemSinkCtrl& memory;

        /** Outgoing packet responses queue */
        RespPacketQueue queue;

      public:
       /**
        * Constructor
        *
        * @param n port name
        * @param m reference to ProfileGen parent object
        */
        MemoryPort(const std::string&, MemSinkCtrl&);

      protected:
       /**
        * Receive a Packet in Atomic mode
        *
        * @param pkt pointer to memory packet
        * @return packet access latency in ticks
        */
        Tick recvAtomic(PacketPtr pkt);

        /**
        * Receive a Packet in Functional mode
        *
        * @param pkt pointer to memory packet
        */
        void recvFunctional(PacketPtr pkt);

        /**
        * Receive a Packet in Timing mode
        *
        * @param pkt pointer to memory packet
        * @return true if the request was accepted
        */
        bool recvTimingReq(PacketPtr pkt);

        /**
         * Gets the configured address ranges for this port
         * @return the configured address ranges for this port
         */
        AddrRangeList getAddrRanges() const;

    };

  public:
    /**
     * QoS Memory Sink Constructor
     *
     * @param p QoS Memory Sink configuration parameters
     */
    MemSinkCtrl(const QoSMemSinkCtrlParams*);

    virtual ~MemSinkCtrl();

    /**
     * Checks and return the Drain state of this SimObject
     * @return current Drain state
     */
    DrainState drain() override;

    /**
     * Getter method to access this memory's response port
     *
     * @param if_name interface name
     * @param idx port ID number
     * @return reference to this memory's response port
     */
    Port &getPort(const std::string &if_name, PortID=InvalidPortID) override;

    /**
     * Initializes this object
     */
    void init() override;

  protected:
    /** Memory between requests latency (ticks) */
    const Tick requestLatency;

    /** Memory response latency (ticks) */
    const Tick responseLatency;

    /** Memory packet size in bytes */
    const uint64_t memoryPacketSize;

    /** Read request packets queue buffer size in #packets */
    const uint64_t readBufferSize;

    /** Write request packets queue buffer size in #packets */
    const uint64_t writeBufferSize;

    /** Memory response port */
    MemoryPort port;

    /**
     * Create pointer to interface of actual media
     */
    QoSMemSinkInterface* const interface;

    /** Read request pending */
    bool retryRdReq;

    /** Write request pending */
    bool retryWrReq;

    /** Next request service time */
    Tick nextRequest;

    /** Count the number of read retries */
    Stats::Scalar numReadRetries;

    /** Count the number of write retries */
    Stats::Scalar numWriteRetries;

    /**
     * QoS-aware (per priority) incoming read requests packets queue
     */
    std::vector<PacketQueue> readQueue;

    /**
     * QoS-aware (per priority) incoming read requests packets queue
     */
    std::vector<PacketQueue> writeQueue;

    /**
     * Processes the next Request event according to configured
     * request latency
     */
    void processNextReqEvent();

    /** Event wrapper to schedule next request handler function */
    EventWrapper<
        MemSinkCtrl,
        &MemSinkCtrl::processNextReqEvent> nextReqEvent;

    /**
     * Check if the read queue has room for more entries
     *
     * @param packets The number of entries needed in the read queue
     * @return true if read queue is full, false otherwise
     */
    inline bool readQueueFull(const uint64_t packets) const;

    /**
     * Check if the write queue has room for more entries
     *
     * @param packets  The number of entries needed in the write queue
     * @return true if write queue is full, false otherwise
     */
    inline bool writeQueueFull(const uint64_t packets) const;

    /**
     * Receive a Packet in Atomic mode
     *
     * @param pkt pointer to memory packet
     * @return packet access latency in ticks
     */
    Tick recvAtomic(PacketPtr pkt);

    /**
     * Receive a Packet in Functional mode
     *
     * @param pkt pointer to memory packet
     */
    void recvFunctional(PacketPtr pkt);

   /**
    * Receive a Packet in Timing mode
    *
    * @param pkt pointer to memory packet
    * @return true if the request was accepted
    */
    bool recvTimingReq(PacketPtr pkt);

    /** Registers statistics */
    void regStats() override;
};

} // namespace QoS

class QoSMemSinkInterface : public AbstractMemory
{
  public:
    /** Setting a pointer to the interface */
    void setMemCtrl(QoS::MemSinkCtrl* _ctrl) { ctrl = _ctrl; };

    /** Pointer to the controller */
    QoS::MemSinkCtrl* ctrl;

    QoSMemSinkInterface(const QoSMemSinkInterfaceParams* _p);
};


#endif /* __MEM_QOS_MEM_SINK_HH__ */
