/*
 * Copyright (c) 2015-2018 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.
 */

#include "dev/hsa/hsa_packet_processor.hh"

#include <cassert>
#include <cstring>

#include "base/chunk_generator.hh"
#include "base/compiler.hh"
#include "base/logging.hh"
#include "base/trace.hh"
#include "debug/HSAPacketProcessor.hh"
#include "dev/dma_device.hh"
#include "dev/hsa/hsa_packet.hh"
#include "dev/hsa/hw_scheduler.hh"
#include "enums/GfxVersion.hh"
#include "gpu-compute/gpu_command_processor.hh"
#include "mem/packet_access.hh"
#include "mem/page_table.hh"
#include "sim/process.hh"
#include "sim/proxy_ptr.hh"
#include "sim/system.hh"

#define HSAPP_EVENT_DESCRIPTION_GENERATOR(XEVENT) \
  const char*                                    \
  HSAPacketProcessor::XEVENT::description() const       \
  {                                              \
      return #XEVENT;                            \
  }

#define PKT_TYPE(PKT) ((hsa_packet_type_t)(((PKT->header) >> \
            HSA_PACKET_HEADER_TYPE) & (HSA_PACKET_HEADER_WIDTH_TYPE - 1)))

// checks if the barrier bit is set in the header -- shift the barrier bit
// to LSB, then bitwise "and" to mask off all other bits
#define IS_BARRIER(PKT) ((hsa_packet_header_t)(((PKT->header) >> \
            HSA_PACKET_HEADER_BARRIER) & HSA_PACKET_HEADER_WIDTH_BARRIER))

namespace gem5
{

HSAPP_EVENT_DESCRIPTION_GENERATOR(QueueProcessEvent)

HSAPacketProcessor::HSAPacketProcessor(const Params &p)
    : DmaVirtDevice(p), numHWQueues(p.numHWQueues), pioAddr(p.pioAddr),
      pioSize(PAGE_SIZE), pioDelay(10), pktProcessDelay(p.pktProcessDelay)
{
    DPRINTF(HSAPacketProcessor, "%s:\n", __FUNCTION__);
    hwSchdlr = new HWScheduler(this, p.wakeupDelay);
    regdQList.resize(numHWQueues);
    for (int i = 0; i < numHWQueues; i++) {
        regdQList[i] = new RQLEntry(this, i);
    }
}

HSAPacketProcessor::~HSAPacketProcessor()
{
    for (auto &queue : regdQList) {
        delete queue;
    }
}

void
HSAPacketProcessor::unsetDeviceQueueDesc(uint64_t queue_id, int doorbellSize)
{
    hwSchdlr->unregisterQueue(queue_id, doorbellSize);
}

void
HSAPacketProcessor::setDeviceQueueDesc(uint64_t hostReadIndexPointer,
                                       uint64_t basePointer,
                                       uint64_t queue_id,
                                       uint32_t size, int doorbellSize,
                                       GfxVersion gfxVersion)
{
    DPRINTF(HSAPacketProcessor,
             "%s:base = %p, qID = %d, ze = %d\n", __FUNCTION__,
             (void *)basePointer, queue_id, size);
    hwSchdlr->registerNewQueue(hostReadIndexPointer,
                               basePointer, queue_id, size, doorbellSize,
                               gfxVersion);
}

AddrRangeList
HSAPacketProcessor::getAddrRanges() const
{
    assert(pioSize != 0);

    AddrRangeList ranges;
    ranges.push_back(RangeSize(pioAddr, pioSize));

    return ranges;
}

// Basically only processes writes to the queue doorbell register.
Tick
HSAPacketProcessor::write(Packet *pkt)
{
    assert(pkt->getAddr() >= pioAddr && pkt->getAddr() < pioAddr + pioSize);

    // TODO: How to get pid??
    [[maybe_unused]] Addr daddr = pkt->getAddr() - pioAddr;

    DPRINTF(HSAPacketProcessor,
          "%s: write of size %d to reg-offset %d (0x%x)\n",
          __FUNCTION__, pkt->getSize(), daddr, daddr);

    assert(gpu_device->driver()->doorbellSize() == pkt->getSize());

    uint64_t doorbell_reg(0);
    if (pkt->getSize() == 8)
        doorbell_reg = pkt->getLE<uint64_t>() + 1;
    else if (pkt->getSize() == 4)
        doorbell_reg = pkt->getLE<uint32_t>();
    else
        fatal("invalid db size");

    DPRINTF(HSAPacketProcessor,
            "%s: write data 0x%x to offset %d (0x%x)\n",
            __FUNCTION__, doorbell_reg, daddr, daddr);
    hwSchdlr->write(daddr, doorbell_reg);
    pkt->makeAtomicResponse();
    return pioDelay;
}

Tick
HSAPacketProcessor::read(Packet *pkt)
{
    pkt->makeAtomicResponse();
    pkt->setBadAddress();
    return pioDelay;
}

TranslationGenPtr
HSAPacketProcessor::translate(Addr vaddr, Addr size)
{
    // Grab the process and try to translate the virtual address with it; with
    // new extensions, it will likely be wrong to just arbitrarily grab context
    // zero.
    auto process = sys->threads[0]->getProcessPtr();

    return process->pTable->translateRange(vaddr, size);
}

/**
 * this event is used to update the read_disp_id field (the read pointer)
 * of the MQD, which is how the host code knows the status of the HQD's
 * read pointer
 */
void
HSAPacketProcessor::updateReadDispIdDma()
{
    DPRINTF(HSAPacketProcessor, "updateReaddispId\n");
}

void
HSAPacketProcessor::updateReadIndex(int pid, uint32_t rl_idx)
{
    AQLRingBuffer* aqlbuf = regdQList[rl_idx]->qCntxt.aqlBuf;
    HSAQueueDescriptor* qDesc = regdQList[rl_idx]->qCntxt.qDesc;
    auto cb = new DmaVirtCallback<uint64_t>(
        [ = ] (const uint32_t &dma_data) { this->updateReadDispIdDma(); }, 0);

    DPRINTF(HSAPacketProcessor,
            "%s: read-pointer offset [0x%x]\n", __FUNCTION__, aqlbuf->rdIdx());

    dmaWriteVirt((Addr)qDesc->hostReadIndexPtr, sizeof(aqlbuf->rdIdx()),
                 cb, aqlbuf->rdIdxPtr());

    DPRINTF(HSAPacketProcessor,
            "%s: rd-ptr offset [0x%x], wr-ptr offset [0x%x], space used = %d," \
            " q size = %d, is_empty = %s, active list ID = %d\n", __FUNCTION__,
            qDesc->readIndex, qDesc->writeIndex, qDesc->spaceUsed(),
            qDesc->numElts, qDesc->isEmpty()? "true" : "false", rl_idx);
    if (qDesc->writeIndex != aqlbuf->wrIdx()) {
        getCommandsFromHost(pid, rl_idx);
    }
}

void
HSAPacketProcessor::cmdQueueCmdDma(HSAPacketProcessor *hsaPP, int pid,
    bool isRead, uint32_t ix_start, unsigned num_pkts,
    dma_series_ctx *series_ctx, void *dest_4debug)
{
    uint32_t rl_idx = series_ctx->rl_idx;
    [[maybe_unused]] AQLRingBuffer *aqlRingBuffer =
        hsaPP->regdQList[rl_idx]->qCntxt.aqlBuf;
    HSAQueueDescriptor* qDesc =
        hsaPP->regdQList[rl_idx]->qCntxt.qDesc;
    DPRINTF(HSAPacketProcessor, ">%s, ix = %d, npkts = %d," \
            " pktsRemaining = %d, active list ID = %d\n", __FUNCTION__,
            ix_start, num_pkts, series_ctx->pkts_2_go,
            rl_idx);
    if (isRead) {
        series_ctx->pkts_2_go -= num_pkts;
        if (series_ctx->pkts_2_go == 0) {
            // Mark DMA as completed
            qDesc->dmaInProgress = false;
            DPRINTF(HSAPacketProcessor,
                    "%s: schedule Qwakeup next cycle, rdIdx %d, wrIdx %d," \
                    " dispIdx %d, active list ID = %d\n",
                    __FUNCTION__, aqlRingBuffer->rdIdx(),
                    aqlRingBuffer->wrIdx(), aqlRingBuffer->dispIdx(), rl_idx);
            // schedule queue wakeup
            hsaPP->schedAQLProcessing(rl_idx);
            delete series_ctx;
        }
    }
}

void
HSAPacketProcessor::schedAQLProcessing(uint32_t rl_idx, Tick delay)
{
    RQLEntry *queue = regdQList[rl_idx];
    if (!queue->aqlProcessEvent.scheduled()) {
        Tick processingTick = curTick() + delay;
        schedule(queue->aqlProcessEvent, processingTick);
        DPRINTF(HSAPacketProcessor, "AQL processing scheduled at tick: %d\n",
                processingTick);
    } else {
        DPRINTF(HSAPacketProcessor, "AQL processing already scheduled\n");
    }
}

void
HSAPacketProcessor::schedAQLProcessing(uint32_t rl_idx)
{
    schedAQLProcessing(rl_idx, pktProcessDelay);
}

Q_STATE
HSAPacketProcessor::processPkt(void* pkt, uint32_t rl_idx, Addr host_pkt_addr)
{
    Q_STATE is_submitted = BLOCKED_BPKT;
    SignalState *dep_sgnl_rd_st = &(regdQList[rl_idx]->depSignalRdState);
    // Dependency signals are not read yet. And this can only be a retry.
    // The retry logic will schedule the packet processor wakeup
    if (dep_sgnl_rd_st->pendingReads != 0) {
        return BLOCKED_BPKT;
    }
    // `pkt` can be typecasted to any type of AQL packet since they all
    // have header information at offset zero
    auto disp_pkt = (_hsa_dispatch_packet_t *)pkt;
    hsa_packet_type_t pkt_type = PKT_TYPE(disp_pkt);
    if (IS_BARRIER(disp_pkt) &&
        regdQList[rl_idx]->compltnPending() > 0) {
        // If this packet is using the "barrier bit" to enforce ordering with
        // previous packets, and if there are outstanding packets, set the
        // barrier bit for this queue and block the queue.
        DPRINTF(HSAPacketProcessor, "%s: setting barrier bit for active" \
                " list ID = %d\n", __FUNCTION__, rl_idx);
        regdQList[rl_idx]->setBarrierBit(true);
        return BLOCKED_BBIT;
    }
    if (pkt_type == HSA_PACKET_TYPE_VENDOR_SPECIFIC) {
        DPRINTF(HSAPacketProcessor, "%s: submitting vendor specific pkt" \
                " active list ID = %d\n", __FUNCTION__, rl_idx);
        // Submit packet to HSA device (dispatcher)
        gpu_device->submitVendorPkt((void *)disp_pkt, rl_idx, host_pkt_addr);
        is_submitted = UNBLOCKED;
    } else if (pkt_type == HSA_PACKET_TYPE_KERNEL_DISPATCH) {
        DPRINTF(HSAPacketProcessor, "%s: submitting kernel dispatch pkt" \
                " active list ID = %d\n", __FUNCTION__, rl_idx);
        // Submit packet to HSA device (dispatcher)
        gpu_device->submitDispatchPkt((void *)disp_pkt, rl_idx, host_pkt_addr);
        is_submitted = UNBLOCKED;
        /*
          If this packet is using the "barrier bit" to enforce ordering with
          subsequent kernels, set the bit for this queue now, after
          dispatching.
        */
        if (IS_BARRIER(disp_pkt)) {
            DPRINTF(HSAPacketProcessor, "%s: setting barrier bit for active" \
                    " list ID = %d\n", __FUNCTION__, rl_idx);
            regdQList[rl_idx]->setBarrierBit(true);
        }
    } else if (pkt_type == HSA_PACKET_TYPE_BARRIER_AND) {
        DPRINTF(HSAPacketProcessor, "%s: Processing barrier packet" \
                " active list ID = %d\n", __FUNCTION__, rl_idx);
        auto bar_and_pkt = (_hsa_barrier_and_packet_t *)pkt;
        bool isReady = true;
        // Loop thorugh all the completion signals to see if this barrier
        // packet is ready.
        for (int i = 0; i < NumSignalsPerBarrier; i++) {
            // dep_signal = zero imply no signal connected
            if (bar_and_pkt->dep_signal[i]) {
                // The signal value is aligned 8 bytes from
                // the actual handle in the runtime
                uint64_t signal_addr =
                    (uint64_t) (((uint64_t *) bar_and_pkt->dep_signal[i]) + 1);
                hsa_signal_value_t *signal_val =
                    &(dep_sgnl_rd_st->values[i]);
                DPRINTF(HSAPacketProcessor, "%s: Barrier pkt dep sgnl[%d]" \
                       " , sig addr %x, value %d active list ID = %d\n",
                       __FUNCTION__, i, signal_addr,
                       *signal_val, rl_idx);
                // The if condition will be executed everytime except the
                // very first time this barrier packet is encounteresd.
                if (dep_sgnl_rd_st->allRead) {
                    if (*signal_val != 0) {
                        // This signal is not yet ready, read it again
                        isReady = false;

                        auto cb = new DmaVirtCallback<int64_t>(
                            [ = ] (const uint32_t &dma_data)
                                { dep_sgnl_rd_st->handleReadDMA(); }, 0);
                        dmaReadVirt(signal_addr, sizeof(hsa_signal_value_t),
                                    cb, signal_val);
                        dep_sgnl_rd_st->pendingReads++;
                        DPRINTF(HSAPacketProcessor, "%s: Pending reads %d," \
                            " active list %d\n", __FUNCTION__,
                            dep_sgnl_rd_st->pendingReads, rl_idx);
                    }
                } else {
                    // This signal is not yet ready, read it again
                    isReady = false;
                    auto cb = new DmaVirtCallback<int64_t>(
                        [ = ] (const uint32_t &dma_data)
                            { dep_sgnl_rd_st->handleReadDMA(); }, 0);
                    dmaReadVirt(signal_addr, sizeof(hsa_signal_value_t),
                                cb, signal_val);
                    dep_sgnl_rd_st->pendingReads++;
                    DPRINTF(HSAPacketProcessor, "%s: Pending reads %d," \
                        " active list %d\n", __FUNCTION__,
                        dep_sgnl_rd_st->pendingReads, rl_idx);
                }
            }
        }
        if (isReady) {
            assert(dep_sgnl_rd_st->pendingReads == 0);
            DPRINTF(HSAPacketProcessor, "%s: Barrier packet completed" \
                    " active list ID = %d\n", __FUNCTION__, rl_idx);
            // TODO: Completion signal of barrier packet to be
            // atomically decremented here
            finishPkt((void*)bar_and_pkt, rl_idx);
            is_submitted = UNBLOCKED;
            // Reset signal values
            dep_sgnl_rd_st->resetSigVals();
            // The completion signal is connected
            if (bar_and_pkt->completion_signal != 0) {
                // HACK: The semantics of the HSA signal is to
                // decrement the current signal value
                // I'm going to cheat here and read out
                // the value from main memory using functional
                // access, and then just DMA the decremented value.
                uint64_t signal_value = gpu_device->functionalReadHsaSignal(\
                                            bar_and_pkt->completion_signal);

                DPRINTF(HSAPacketProcessor, "Triggering barrier packet" \
                       " completion signal! Addr: %x\n",
                       bar_and_pkt->completion_signal);

                gpu_device->updateHsaSignal(bar_and_pkt->completion_signal,
                                            signal_value - 1);
            }
        }
        if (dep_sgnl_rd_st->pendingReads > 0) {
            // Atleast one DepSignalsReadDmaEvent is scheduled this cycle
            dep_sgnl_rd_st->allRead = false;
            dep_sgnl_rd_st->discardRead = false;
        }
    } else if (pkt_type == HSA_PACKET_TYPE_BARRIER_OR) {
        fatal("Unsupported packet type HSA_PACKET_TYPE_BARRIER_OR");
    } else if (pkt_type == HSA_PACKET_TYPE_INVALID) {
        fatal("Unsupported packet type HSA_PACKET_TYPE_INVALID");
    } else if (pkt_type == HSA_PACKET_TYPE_AGENT_DISPATCH) {
        DPRINTF(HSAPacketProcessor, "%s: submitting agent dispatch pkt" \
                " active list ID = %d\n", __FUNCTION__, rl_idx);
        // Submit packet to HSA device (dispatcher)
        gpu_device->submitAgentDispatchPkt(
                (void *)disp_pkt, rl_idx, host_pkt_addr);
        is_submitted = UNBLOCKED;
        sendAgentDispatchCompletionSignal((void *)disp_pkt,0);
    } else {
        fatal("Unsupported packet type %d\n", pkt_type);
    }
    return is_submitted;
}

// Wakes up every fixed time interval (pktProcessDelay) and processes a single
// packet from the queue that scheduled this wakeup. If there are more
// packets in that queue, the next wakeup is scheduled.
void
HSAPacketProcessor::QueueProcessEvent::process()
{
    AQLRingBuffer *aqlRingBuffer = hsaPP->regdQList[rqIdx]->qCntxt.aqlBuf;
    DPRINTF(HSAPacketProcessor,
            "%s: Qwakeup , rdIdx %d, wrIdx %d," \
            " dispIdx %d, active list ID = %d\n",
            __FUNCTION__, aqlRingBuffer->rdIdx(),
            aqlRingBuffer->wrIdx(), aqlRingBuffer->dispIdx(), rqIdx);
    // If barrier bit is set, then this wakeup is a dummy wakeup
    // just to model the processing time. Do nothing.
    if (hsaPP->regdQList[rqIdx]->getBarrierBit()) {
        DPRINTF(HSAPacketProcessor,
            "Dummy wakeup with barrier bit for rdIdx %d\n", rqIdx);
        return;
    }
    // In the future, we may support batch processing of packets.
    // Then, we can just remove the break statements and the code
    // will support batch processing. That is why we are using a
    // "while loop" here instead on an "if" condition.
    while (hsaPP->regdQList[rqIdx]->dispPending()) {
        void *pkt = aqlRingBuffer->ptr(aqlRingBuffer->dispIdx());
        DPRINTF(HSAPacketProcessor, "%s: Attempting dispatch @ dispIdx[%d]\n",
                __FUNCTION__, aqlRingBuffer->dispIdx());
        Addr host_addr = aqlRingBuffer->hostDispAddr();
        Q_STATE q_state = hsaPP->processPkt(pkt, rqIdx, host_addr);
        if (q_state == UNBLOCKED) {
             aqlRingBuffer->incDispIdx(1);
             DPRINTF(HSAPacketProcessor, "%s: Increment dispIdx[%d]\n",
                     __FUNCTION__, aqlRingBuffer->dispIdx());
             if (hsaPP->regdQList[rqIdx]->dispPending()) {
                 hsaPP->schedAQLProcessing(rqIdx);
             }
             break;
        } else if (q_state == BLOCKED_BPKT) {
            // This queue is blocked by barrier packet,
            // schedule a processing event
            hsaPP->schedAQLProcessing(rqIdx);
            break;
        } else if (q_state == BLOCKED_BBIT) {
            // This queue is blocked by barrier bit, and processing event
            // should be scheduled from finishPkt(). However, to elapse
            // "pktProcessDelay" processing time, let us schedule a dummy
            // wakeup once which will just wakeup and will do nothing.
            hsaPP->schedAQLProcessing(rqIdx);
            break;
        } else {
            panic("Unknown queue state\n");
        }
    }
}

void
HSAPacketProcessor::SignalState::handleReadDMA()
{
    assert(pendingReads > 0);
    pendingReads--;
    if (pendingReads == 0) {
        allRead = true;
        if (discardRead) {
            resetSigVals();
        }
    }
}

void
HSAPacketProcessor::getCommandsFromHost(int pid, uint32_t rl_idx)
{
    HSAQueueDescriptor* qDesc = regdQList[rl_idx]->qCntxt.qDesc;
    AQLRingBuffer *aqlRingBuffer = regdQList[rl_idx]->qCntxt.aqlBuf;

    DPRINTF(HSAPacketProcessor,
            "%s: read-pointer offset[0x%x], write-pointer offset[0x%x]"
            " doorbell(%d)[0x%x] \n",
            __FUNCTION__, qDesc->readIndex,
            qDesc->writeIndex, pid, qDesc->doorbellPointer);

    if (qDesc->dmaInProgress) {
        // we'll try again when this dma transfer completes in updateReadIndex
        return;
    }
    uint32_t num_umq = qDesc->spaceUsed();
    if (num_umq == 0)
        return; // nothing to be gotten
    uint32_t umq_nxt = qDesc->readIndex;
    // Total AQL buffer size
    uint32_t ttl_aql_buf = aqlRingBuffer->numObjs();
    // Available AQL buffer size. If the available buffer is less than
    // demanded, number of available buffer is returned
    uint32_t got_aql_buf = aqlRingBuffer->allocEntry(num_umq);
    qDesc->readIndex += got_aql_buf;
    uint32_t dma_start_ix = (aqlRingBuffer->wrIdx() - got_aql_buf) %
        ttl_aql_buf;
    dma_series_ctx *series_ctx = NULL;

    DPRINTF(HSAPacketProcessor, "%s: umq_nxt = %d, ttl_aql_buf = %d, "
            "dma_start_ix = %d, num_umq = %d\n", __FUNCTION__, umq_nxt,
            ttl_aql_buf, dma_start_ix, num_umq);

    if (got_aql_buf == 0) {
        // we'll try again when some dma bufs are freed in freeEntry
        qDesc->stalledOnDmaBufAvailability = true;
        return;
    } else {
        qDesc->stalledOnDmaBufAvailability = false;
    }

    uint32_t dma_b4_wrap = ttl_aql_buf - dma_start_ix;
    while (got_aql_buf != 0 && num_umq != 0) {
        uint32_t umq_b4_wrap = qDesc->numObjs() -
            (umq_nxt % qDesc->objSize());
        uint32_t num_2_xfer
            = std::min({umq_b4_wrap, dma_b4_wrap, num_umq, got_aql_buf});
        if (!series_ctx) {
            qDesc->dmaInProgress = true;
            series_ctx = new dma_series_ctx(got_aql_buf, got_aql_buf,
                                            dma_start_ix, rl_idx);
        }

        void *aql_buf = aqlRingBuffer->ptr(dma_start_ix);
        auto cb = new DmaVirtCallback<uint64_t>(
            [ = ] (const uint32_t &dma_data)
                { this->cmdQueueCmdDma(this, pid, true, dma_start_ix,
                                num_2_xfer, series_ctx, aql_buf); }, 0);
        dmaReadVirt(qDesc->ptr(umq_nxt), num_2_xfer * qDesc->objSize(),
                    cb, aql_buf);

        aqlRingBuffer->saveHostDispAddr(qDesc->ptr(umq_nxt), num_2_xfer,
                                        dma_start_ix);

        DPRINTF(HSAPacketProcessor,
                "%s: aql_buf = %p, umq_nxt = %d, dma_ix = %d, num2xfer = %d\n",
                __FUNCTION__, aql_buf, umq_nxt, dma_start_ix, num_2_xfer);

        num_umq -= num_2_xfer;
        got_aql_buf -= num_2_xfer;
        dma_start_ix = (dma_start_ix + num_2_xfer) % ttl_aql_buf;
        umq_nxt = (umq_nxt + num_2_xfer) % qDesc->numObjs();
        if (got_aql_buf == 0 && num_umq != 0) {
            // There are more packets in the queue but
            // not enough DMA buffers. Set the stalledOnDmaBufAvailability,
            // we will try again in freeEntry
            qDesc->stalledOnDmaBufAvailability = true;
        }
    }
}

void
HSAPacketProcessor::displayQueueDescriptor(int pid, uint32_t rl_idx)
{
    [[maybe_unused]] HSAQueueDescriptor* qDesc =
        regdQList[rl_idx]->qCntxt.qDesc;
    DPRINTF(HSAPacketProcessor,
            "%s: pid[%d], basePointer[0x%lx], dBPointer[0x%lx], "
            "writeIndex[0x%x], readIndex[0x%x], size(bytes)[0x%x]\n",
            __FUNCTION__, pid, qDesc->basePointer,
            qDesc->doorbellPointer, qDesc->writeIndex,
            qDesc->readIndex, qDesc->numElts);
}

AQLRingBuffer::AQLRingBuffer(uint32_t size,
                             const std::string name)
        : _name(name), _wrIdx(0), _rdIdx(0), _dispIdx(0)
{
    _aqlBuf.resize(size);
    _aqlComplete.resize(size);
    _hostDispAddresses.resize(size);
    // Mark all packets as invalid and incomplete
    for (auto& it : _aqlBuf)
        it.header = HSA_PACKET_TYPE_INVALID;
    std::fill(_aqlComplete.begin(), _aqlComplete.end(), false);
}

bool
AQLRingBuffer::freeEntry(void *pkt)
{
    _aqlComplete[(hsa_kernel_dispatch_packet_t *) pkt - _aqlBuf.data()] = true;
    DPRINTF(HSAPacketProcessor, "%s: pkt_ix = %d; "\
            " # free entries = %d, wrIdx = %d, rdIdx = %d\n", __FUNCTION__,
            (hsa_kernel_dispatch_packet_t *) pkt - _aqlBuf.data(),
            nFree(), wrIdx(), rdIdx());
    // Packets can complete out-of-order. This code "retires" packets in-order
    // by updating the read pointer in the MQD when a contiguous chunk of
    // packets have finished.
    uint32_t old_rdIdx = rdIdx();
    while (_aqlComplete[rdIdx() % numObjs()]) {
       _aqlComplete[rdIdx() % numObjs()] = false;
       _aqlBuf[rdIdx() % numObjs()].header = HSA_PACKET_TYPE_INVALID;
       incRdIdx(1);
    }
    return (old_rdIdx != rdIdx());
}

void
HSAPacketProcessor::setDevice(GPUCommandProcessor *dev)
{
    this->gpu_device = dev;
}

int
AQLRingBuffer::allocEntry(uint32_t nBufReq)
{
    DPRINTF(HSAPacketProcessor, "%s: nReq = %d\n", __FUNCTION__, nBufReq);
    if (nFree() == 0) {
        DPRINTF(HSAPacketProcessor, "%s: return = %d\n", __FUNCTION__, 0);
        return 0;
    }

    if (nBufReq > nFree())
        nBufReq = nFree();

    DPRINTF(HSAPacketProcessor, "%s: ix1stFree = %d\n", __FUNCTION__, wrIdx());
    incWrIdx(nBufReq);
    DPRINTF(HSAPacketProcessor, "%s: return = %d, wrIdx = %d\n",
            __FUNCTION__, nBufReq, wrIdx());
    return nBufReq;
}

void
HSAPacketProcessor::finishPkt(void *pvPkt, uint32_t rl_idx)
{
    HSAQueueDescriptor* qDesc = regdQList[rl_idx]->qCntxt.qDesc;

    // if barrier bit was set and this is the last
    // outstanding packet from that queue,
    // unset it here
    if (regdQList[rl_idx]->getBarrierBit() &&
        regdQList[rl_idx]->isLastOutstandingPkt()) {
        DPRINTF(HSAPacketProcessor,
                "Unset barrier bit for active list ID %d\n", rl_idx);
        regdQList[rl_idx]->setBarrierBit(false);
        // if pending kernels in the queue after this kernel, reschedule
        if (regdQList[rl_idx]->dispPending()) {
            DPRINTF(HSAPacketProcessor,
                    "Rescheduling active list ID %d after unsetting barrier "
                    "bit\n", rl_idx);
            schedAQLProcessing(rl_idx);
        }
    }

    // If set, then blocked schedule, so need to reschedule
    if (regdQList[rl_idx]->qCntxt.aqlBuf->freeEntry(pvPkt))
        updateReadIndex(0, rl_idx);
    DPRINTF(HSAPacketProcessor,
            "%s: rd-ptr offset [0x%x], wr-ptr offset [0x%x], space used = %d," \
            " q size = %d, stalled = %s, empty = %s, active list ID = %d\n",
            __FUNCTION__, qDesc->readIndex, qDesc->writeIndex,
            qDesc->spaceUsed(), qDesc->numElts,
            qDesc->stalledOnDmaBufAvailability? "true" : "false",
            qDesc->isEmpty()? "true" : "false", rl_idx);
    // DMA buffer is freed, check the queue to see if there are DMA
    // accesses blocked becasue of non-availability of DMA buffer
    if (qDesc->stalledOnDmaBufAvailability) {
        assert(!qDesc->isEmpty());
        getCommandsFromHost(0, rl_idx); // TODO:assign correct pid
                                        // when implementing
                                        // multi-process support
    }
}

void
HSAPacketProcessor::sendAgentDispatchCompletionSignal(
    void *pkt, hsa_signal_value_t signal)
{
    auto agent_pkt = (_hsa_agent_dispatch_packet_t *)pkt;
    uint64_t signal_addr =
            (uint64_t) (((uint64_t *)agent_pkt->completion_signal) + 1);
    DPRINTF(HSAPacketProcessor, "Triggering Agent Dispatch packet" \
            " completion signal: %x!\n", signal_addr);
    /**
     * HACK: The semantics of the HSA signal is to
     * decrement the current signal value.
     * I'm going to cheat here and read out
     * the value from main memory using functional
     * access, and then just DMA the decremented value.
     * The reason for this is that the DMASequencer does
     * not support atomic operations.
     */
    VPtr<uint64_t> prev_signal(signal_addr, sys->threads[0]);

    DPRINTF(HSAPacketProcessor,"HSADriver: Sending signal to %lu\n",
            (uint64_t)sys->threads[0]->cpuId());


    hsa_signal_value_t *new_signal = new hsa_signal_value_t;
    *new_signal = (hsa_signal_value_t) *prev_signal - 1;

    dmaWriteVirt(signal_addr, sizeof(hsa_signal_value_t), nullptr, new_signal, 0);
}

void
HSAPacketProcessor::sendCompletionSignal(hsa_signal_value_t signal)
{
    uint64_t signal_addr = (uint64_t) (((uint64_t *)signal) + 1);
    DPRINTF(HSAPacketProcessor, "Triggering completion signal: %x!\n",
            signal_addr);
    /**
     * HACK: The semantics of the HSA signal is to
     * decrement the current signal value.
     * I'm going to cheat here and read out
     * the value from main memory using functional
     * access, and then just DMA the decremented value.
     * The reason for this is that the DMASequencer does
     * not support atomic operations.
     */
    VPtr<uint64_t> prev_signal(signal_addr, sys->threads[0]);

    hsa_signal_value_t *new_signal = new hsa_signal_value_t;
    *new_signal = (hsa_signal_value_t) *prev_signal - 1;

    dmaWriteVirt(signal_addr, sizeof(hsa_signal_value_t), nullptr, new_signal, 0);
}

} // namespace gem5
