/*
 * 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_INTERRUPT_HANDLER__
#define __DEV_AMDGPU_INTERRUPT_HANDLER__

#include <bitset>
#include <iostream>
#include <queue>
#include <vector>

#include "base/addr_range.hh"
#include "base/flags.hh"
#include "base/types.hh"
#include "dev/amdgpu/amdgpu_device.hh"
#include "dev/dma_device.hh"
#include "params/AMDGPUInterruptHandler.hh"

namespace gem5
{

/**
 * Defines from driver code. Taken from
 * https://github.com/RadeonOpenCompute/ROCK-Kernel-Driver/blob/roc-4.3.x/
 *     drivers/gpu/drm/amd/include/soc15_ih_clientid.h
 */
enum soc15_ih_clientid
{
    SOC15_IH_CLIENTID_RLC       = 0x07,
    SOC15_IH_CLIENTID_SDMA0     = 0x08,
    SOC15_IH_CLIENTID_SDMA1     = 0x09
};

enum ihSourceId
{
    TRAP_ID                     = 224
};

/**
 * MSI-style interrupts. Send a "cookie" response to clear interrupts.
 * From [1] we know the size of the struct is 8 dwords. Then we can look at the register shift offsets in [2] to guess the rest.
 * Or we can also look at [3].
 *
 * [1] https://github.com/RadeonOpenCompute/ROCK-Kernel-Driver/blob/roc-4.3.x/
 *         drivers/gpu/drm/amd/amdkfd/kfd_device.c#L316
 * [2] https://github.com/RadeonOpenCompute/ROCK-Kernel-Driver/blob/roc-4.3.x/
 *         drivers/gpu/drm/amd/include/asic_reg/oss/osssys_4_0_sh_mask.h#L122
 * [3] https://github.com/RadeonOpenCompute/ROCK-Kernel-Driver/blob/roc-4.3.x/
           drivers/gpu/drm/amd/amdgpu/amdgpu_irq.h#L46
 *
 */
constexpr uint32_t INTR_COOKIE_SIZE = 32; // in bytes

typedef struct
{
    uint32_t clientId : 8;
    uint32_t sourceId : 8;
    uint32_t ringId : 8;
    uint32_t vmId : 4;
    uint32_t reserved1 : 3;
    uint32_t vmid_type : 1;
    uint32_t timestamp_Lo;
    uint32_t timestamp_Hi : 16;
    uint32_t reserved2 : 15;
    uint32_t timestamp_src : 1;
    uint32_t pasid : 16;
    uint32_t reserved3 : 15;
    uint32_t pasid_src : 1;
    uint32_t source_data_dw1;
    uint32_t source_data_dw2;
    uint32_t source_data_dw3;
    uint32_t source_data_dw4;
} AMDGPUInterruptCookie;
static_assert(sizeof(AMDGPUInterruptCookie) == INTR_COOKIE_SIZE);

/**
 * Struct to contain all interrupt handler related registers.
 */
typedef struct
{
    uint32_t IH_Cntl;
    uint32_t IH_Base;
    uint32_t IH_Base_Hi;
    Addr baseAddr;
    uint32_t IH_Rptr;
    uint32_t IH_Wptr;
    uint32_t IH_Wptr_Addr_Lo;
    uint32_t IH_Wptr_Addr_Hi;
    Addr WptrAddr;
    uint32_t IH_Doorbell;
} AMDGPUIHRegs;

class AMDGPUInterruptHandler : public DmaDevice
{
  public:
    class DmaEvent : public Event
    {
      private:
        AMDGPUInterruptHandler *deviceIh;
        uint32_t data;

      public:
        DmaEvent(AMDGPUInterruptHandler *deviceIh, uint32_t data)
            : Event(), deviceIh(deviceIh), data(data)
        {
            setFlags(Event::AutoDelete);
        }
        void process();
        const char *description() const {
            return "AMDGPUInterruptHandler Dma";
        }

        void setData(uint32_t _data) { data = _data; }
        uint32_t getData() { return data; }
    };

    struct SenderState : public Packet::SenderState
    {
        SenderState(Packet::SenderState *sender_state, Addr addr)
            : saved(sender_state), _addr(addr)
        {
        }
        Packet::SenderState *saved;
        Addr _addr;
    };

    AMDGPUInterruptHandler(const AMDGPUInterruptHandlerParams &p);

    Tick write(PacketPtr pkt) override { return 0; }
    Tick read(PacketPtr pkt) override { return 0; }
    AddrRangeList getAddrRanges() const override;
    void serialize(CheckpointOut &cp) const override;
    void unserialize(CheckpointIn &cp) override;

    void setGPUDevice(AMDGPUDevice *gpu_device) { gpuDevice = gpu_device; }
    void prepareInterruptCookie(ContextID cntxtId, uint32_t ring_id,
        uint32_t client_id, uint32_t source_id);
    void submitInterruptCookie();
    void submitWritePointer();
    void intrPost();

    /**
     * Methods for setting the values of interrupt handler MMIO registers.
     */
    void writeMMIO(PacketPtr pkt, Addr mmio_offset);

    uint32_t getDoorbellOffset() const { return regs.IH_Doorbell; }
    void setCntl(const uint32_t &data);
    void setBase(const uint32_t &data);
    void setBaseHi(const uint32_t &data);
    void setRptr(const uint32_t &data);
    void setWptr(const uint32_t &data);
    void setWptrAddrLo(const uint32_t &data);
    void setWptrAddrHi(const uint32_t &data);
    void setDoorbellOffset(const uint32_t &data);
    void updateRptr(const uint32_t &data);

  private:
    AMDGPUDevice *gpuDevice;
    AMDGPUIHRegs regs;
    std::queue<AMDGPUInterruptCookie*> interruptQueue;
    AMDGPUInterruptHandler::DmaEvent *dmaEvent;
};

} // namespace gem5

#endif // __DEV_AMDGPU_INTERRUPT_HANDLER__
