/*
 * Copyright (c) 2021 Advanced Micro Devices, Inc.
 * All rights reserved.
 *
 * 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 __DEV_AMDGPU_PAGETABLE_WALKER_HH__
#define __DEV_AMDGPU_PAGETABLE_WALKER_HH__

#include <vector>

#include "arch/amdgpu/vega/pagetable.hh"
#include "arch/amdgpu/vega/tlb.hh"
#include "base/types.hh"
#include "debug/GPUPTWalker.hh"
#include "mem/packet.hh"
#include "params/VegaPagetableWalker.hh"
#include "sim/clocked_object.hh"
#include "sim/system.hh"

namespace gem5
{

class ThreadContext;

namespace VegaISA
{

class Walker : public ClockedObject
{
  protected:
    // Port for accessing memory
    class WalkerPort : public RequestPort
    {
      public:
        WalkerPort(const std::string &_name, Walker * _walker) :
            RequestPort(_name, _walker), walker(_walker)
        {}

      protected:
        Walker *walker;

        bool recvTimingResp(PacketPtr pkt);
        void recvReqRetry();
    };

    friend class WalkerPort;
    WalkerPort port;

    // State to track each walk of the page table
    class WalkerState
    {
        friend class Walker;

      private:
        enum State
        {
            Ready,
            Waiting,
            PDE2, PDE1, PDE0, PTE
        };

      protected:
        Walker *walker;
        State state;
        State nextState;
        int dataSize;
        bool enableNX;
        VegaTlbEntry entry;
        PacketPtr read;
        Fault timingFault;
        BaseMMU::Mode mode;
        bool retrying;
        bool started;
        bool timing;
        PacketPtr tlbPkt;

      public:
        WalkerState(Walker *_walker, PacketPtr pkt, bool is_functional = false)
            : walker(_walker), state(Ready), nextState(Ready), dataSize(8),
              enableNX(true), retrying(false), started(false), tlbPkt(pkt)
        {
            DPRINTF(GPUPTWalker, "Walker::WalkerState %p %p %d\n",
                    this, walker, state);
        }

        void initState(BaseMMU::Mode _mode, Addr baseAddr, Addr vaddr,
                       bool is_functional = false);
        void startWalk();
        Fault startFunctional(Addr base, Addr vaddr, PageTableEntry &pte,
                              unsigned &logBytes);

        bool isRetrying();
        void retry();
        std::string name() const { return walker->name(); }
        Walker* getWalker() const { return walker; }

      private:
        Fault stepWalk();
        void stepTimingWalk();
        void walkStateMachine(PageTableEntry &pte, Addr &nextRead,
                              bool &doEndWalk, Fault &fault);
        void sendPackets();
        void endWalk();
        Fault pageFault(bool present);
        uint64_t offsetFunc(Addr logicalAddr, int top, int lsb);
    };

    friend class WalkerState;
    // State for timing and atomic accesses (need multiple per walker in
    // the case of multiple outstanding requests in timing mode)
    std::list<WalkerState *> currStates;
    // State for functional accesses (only need one of these per walker)
    WalkerState funcState;

    struct WalkerSenderState : public Packet::SenderState
    {
        WalkerState * senderWalk;
        WalkerSenderState(WalkerState * _senderWalk) :
            senderWalk(_senderWalk) {}
    };

  public:
    // Kick off the state machine.
    void startTiming(PacketPtr pkt, Addr base, Addr vaddr, BaseMMU::Mode mode);
    Fault startFunctional(Addr base, Addr vaddr, PageTableEntry &pte,
                          unsigned &logBytes, BaseMMU::Mode mode);
    Fault startFunctional(Addr base, Addr &addr, unsigned &logBytes,
                          BaseMMU::Mode mode, bool &isSystem);

    Port &getPort(const std::string &if_name,
                  PortID idx=InvalidPortID) override;

    Addr getBaseAddr() const { return baseAddr; }
    void setBaseAddr(Addr ta) { baseAddr = ta; }

    void setDevRequestor(RequestorID mid) { deviceRequestorId = mid; }
    RequestorID getDevRequestor() const { return deviceRequestorId; }

  protected:
    // The TLB we're supposed to load.
    GpuTLB *tlb;
    RequestorID requestorId;

    // Base address set by MAP_PROCESS packet
    Addr baseAddr;
    RequestorID deviceRequestorId;

    // Functions for dealing with packets.
    void recvTimingResp(PacketPtr pkt);
    void recvReqRetry();
    bool sendTiming(WalkerState * sendingState, PacketPtr pkt);

    void walkerResponse(WalkerState *state, VegaTlbEntry& entry,
                        PacketPtr pkt);

    // System pointer for functional accesses
    System *system;

  public:
    void setTLB(GpuTLB * _tlb)
    {
        assert(tlb == nullptr); // only set it once
        tlb = _tlb;
    }

    Walker(const VegaPagetableWalkerParams &p)
      : ClockedObject(p),
        port(name() + ".port", this),
        funcState(this, nullptr, true), tlb(nullptr),
        requestorId(p.system->getRequestorId(this)),
        deviceRequestorId(999), system(p.system)
    {
        DPRINTF(GPUPTWalker, "Walker::Walker %p\n", this);
    }
};

} // namespace VegaISA
} // namespace gem5

#endif // __DEV_AMDGPU_PAGETABLE_WALKER_HH__
