/*
 * Copyright (c) 2016-2020 Advanced Micro Devices, Inc.
 * All rights reserved.
 *
 * For use for simulation and test purposes only
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are met:
 *
 * 1. Redistributions of source code must retain the above copyright notice,
 * this list of conditions and the following disclaimer.
 *
 * 2. 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.
 *
 * 3. Neither the name of the copyright holder 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 HOLDER 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.
 */

#ifndef __MEM_TOKEN_PORT_HH__
#define __MEM_TOKEN_PORT_HH__

#include "mem/port.hh"
#include "sim/clocked_object.hh"

class TokenManager;
class TokenSlavePort;

class TokenMasterPort : public RequestPort
{
  private:
    /* Manager to track tokens between this token port pair. */
    TokenManager *tokenManager;

  public:
    TokenMasterPort(const std::string& name, SimObject* owner,
                    PortID id = InvalidPortID) :
        RequestPort(name, owner, id), tokenManager(nullptr)
    { }

    /**
     * Bind this master port to slave port. Called by the slave port in
     * this token implementation.
     */
    void bind(Port &peer) override;

    /**
     * Unbind port. Handled by slave port in token implementation.
     */
    void unbind() override {}

    /**
     * Receive tokens returned by the slave port. This increments the number
     * or available tokens across the port.
     */
    void recvTokens(int num_tokens);

    /**
     * Query if there are at least num_tokens tokens available to acquire.
     */
    bool haveTokens(int num_tokens);

    /**
     * Acquire tokens by decrementing the number of available tokens across
     * the port. This does the opposite of recvTokens.
     */
    void acquireTokens(int num_tokens);

    /**
     * Specify a token manger, which will handle tracking of tokens for a
     * TokenMasterPort/SlaveMasterPort pair.
     */
    void setTokenManager(TokenManager *_tokenManager);
};

class TokenSlavePort : public ResponsePort
{
  private:
    TokenMasterPort *tokenMasterPort;

    std::deque<PacketPtr> respQueue;

    void recvRespRetry() override;

  public:
    TokenSlavePort(const std::string& name, ClockedObject *owner,
                   PortID id = InvalidPortID) :
        ResponsePort(name, owner, id), tokenMasterPort(nullptr)
    { }
    ~TokenSlavePort() { }

    /**
     * Bind this slave port to a master port. This also does the mirror
     * action and bainds the master port to the slave port as well as
     * binding the base class types.
     */
    void bind(Port &peer) override;

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

    /**
     * Return num_tokens tokens back to the master port.
     */
    void sendTokens(int num_tokens);

    bool sendTimingResp(PacketPtr pkt);

    /* There is no storage here so the packet will not be found. */
    bool trySatisfyFunctional(PacketPtr) { return false; }
};

class TokenManager
{
  protected:
    /* Maximum tokens possible */
    int maxTokens;

    /* Number of currently available tokens */
    int availableTokens;

  public:
    TokenManager(int init_tokens);
    ~TokenManager() { }

    /**
     * Return the maximum possible tokens.
     */
    int getMaxTokenCount() const;

    /**
     * Increment the number of available tokens by num_tokens.
     */
    void recvTokens(int num_tokens);

    /**
     * Query is num_tokens tokens are available.
     */
    bool haveTokens(int num_tokens);

    /**
     * Decrement the number of available tokens by num_tokens.
     */
    void acquireTokens(int num_tokens);
};

#endif
