/*
 * Copyright (c) 2016-2017 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/hw_scheduler.hh"

#include "base/compiler.hh"
#include "base/trace.hh"
#include "debug/HSAPacketProcessor.hh"
#include "sim/cur_tick.hh"

#define HWSCHDLR_EVENT_DESCRIPTION_GENERATOR(XEVENT) \
  const char*                                    \
  HWScheduler::XEVENT::description() const       \
  {                                              \
      return #XEVENT;                            \
  }

namespace gem5
{

HWSCHDLR_EVENT_DESCRIPTION_GENERATOR(SchedulerWakeupEvent)

void
HWScheduler::SchedulerWakeupEvent::process()
{
    hwSchdlr->wakeup();
}

void
HWScheduler::wakeup()
{
    // The scheduler unmaps an idle queue from the
    // registered qList and maps a new queue
    // to the registered list from the active list.
    // For this implementation, an idle queue means
    // a queue that does not have any outstanding dispatch
    // at the time of this scheduler's wakeup

    contextSwitchQ();
    schedWakeup();
}

void
HWScheduler::schedWakeup()
{
    // If atleast there is one queue that is not registered
    // then wakeup again
    if (!schedWakeupEvent.scheduled() &&
        regdListMap.size() < activeList.size()) {
        hsaPP->schedule(&schedWakeupEvent, curTick() + wakeupDelay);
        DPRINTF(HSAPacketProcessor,
                "Scheduling wakeup at %lu\n", (curTick() + wakeupDelay));
    }
}

void
HWScheduler::registerNewQueue(uint64_t hostReadIndexPointer,
                              uint64_t basePointer,
                              uint64_t queue_id,
                              uint32_t size, int doorbellSize)
{
    assert(queue_id < MAX_ACTIVE_QUEUES);
    // Map queue ID to doorbell.
    // We are only using offset to pio base address as doorbell
    // We use the same mapping function used by hsa runtime to do this mapping
    Addr db_offset = queue_id * doorbellSize;
    if (dbMap.find(db_offset) != dbMap.end()) {
        panic("Creating an already existing queue (queueID %d)", queue_id);
    }

    // Populate doorbell map
    dbMap[db_offset] = queue_id;

    if (queue_id >= MAX_ACTIVE_QUEUES) {
        panic("Attempting to create a queue (queueID %d)" \
              " beyond PIO range", queue_id);
    }

    HSAQueueDescriptor* q_desc =
       new HSAQueueDescriptor(basePointer, db_offset,
                              hostReadIndexPointer, size);
    AQLRingBuffer* aql_buf =
        new AQLRingBuffer(NUM_DMA_BUFS, hsaPP->name());
    QCntxt q_cntxt(q_desc, aql_buf);
    activeList[dbMap[db_offset]] = q_cntxt;

    // Check if this newly created queue can be directly mapped
    // to registered queue list
    GEM5_VAR_USED bool register_q = mapQIfSlotAvlbl(queue_id, aql_buf, q_desc);
    schedWakeup();
    DPRINTF(HSAPacketProcessor,
             "%s: offset = %p, qID = %d, is_regd = %s, AL size %d\n",
             __FUNCTION__, db_offset, queue_id,
             (register_q) ? "true" : "false", dbMap.size());
}

bool
HWScheduler::findEmptyHWQ()
{
    DPRINTF(HSAPacketProcessor,
            "Trying to find empty HW queue, @ %s\n", __FUNCTION__);
    if (regdListMap.size() < hsaPP->numHWQueues) {
        for (int emptyQId = 0; emptyQId < hsaPP->numHWQueues; emptyQId++) {
            HSAQueueDescriptor* qDesc =
                hsaPP->getRegdListEntry(nextRLId)->qCntxt.qDesc;
            // If qDesc is empty, we find an empty HW queue
            if (qDesc == NULL) {
                return true;
            }
            nextRLId = (nextRLId + 1) % hsaPP->numHWQueues;
        }
        // We should be able to find an empty slot in registered list
        // So, we should not reach here
        panic("Cannot find empty queue\n");
    }
    return false;
}

bool
HWScheduler::mapQIfSlotAvlbl(uint32_t q_id, AQLRingBuffer* aql_buf,
                             HSAQueueDescriptor* q_desc)
{
    DPRINTF(HSAPacketProcessor,
            "Trying to map new queue, @ %s\n", __FUNCTION__);
    if (!findEmptyHWQ()) {
        return false;
    }
    addQCntxt(q_id, aql_buf, q_desc);
    scheduleAndWakeupMappedQ();
    updateRRVars(q_id, nextRLId);
    return true;
}

void
HWScheduler::scheduleAndWakeupMappedQ()
{
    // There maybe AQL packets in the mapped queue waiting
    // to be fetched. Invoke the logic to fetch AQL packets
    hsaPP->getCommandsFromHost(0, nextRLId);
    // Schedule the newly mapped queue
    if (hsaPP->regdQList[nextRLId]->dispPending())
        hsaPP->schedAQLProcessing(nextRLId);
}

void
HWScheduler::addQCntxt(uint32_t al_idx, AQLRingBuffer* aql_buf,
                        HSAQueueDescriptor* q_desc)
{
    assert(hsaPP->getRegdListEntry(nextRLId)->qCntxt.qDesc == NULL);
    assert(hsaPP->getRegdListEntry(nextRLId)->qCntxt.aqlBuf == NULL);
    // Move the context
    hsaPP->getRegdListEntry(nextRLId)->qCntxt.qDesc = q_desc;
    hsaPP->getRegdListEntry(nextRLId)->qCntxt.aqlBuf = aql_buf;
    // Add the mapping to registered list map
    regdListMap[al_idx] = nextRLId;
    DPRINTF(HSAPacketProcessor, "Mapped HSA queue %d to hw queue %d: @ %s\n",
            al_idx, nextRLId, __FUNCTION__);
}

bool
HWScheduler::contextSwitchQ()
{
    DPRINTF(HSAPacketProcessor,
            "Trying to map next queue, @ %s", __FUNCTION__);
    // Identify the next queue, if there is nothing to
    // map, return false
    if (!findNextActiveALQ()) {
        return false;
    }
    HSAQueueDescriptor* q_desc = activeList[nextALId].qDesc;
    AQLRingBuffer* aql_buf = activeList[nextALId].aqlBuf;
    // If there is empty slot available, use that slot
    if(mapQIfSlotAvlbl(nextALId, aql_buf, q_desc)) {
        return true;
    }
    // There is no empty slot to map this queue. So, we need to
    // unmap a queue from registered list and find a slot.
    // If nothing can be unmapped now, return false
    if (!unmapQFromRQ()) {
        return false;
    }
    // One queue is unmapped from registered list and that queueID
    // is stored in nextRLId. We will map this queue to that unmapped slot
    addQCntxt(nextALId, aql_buf, q_desc);
    scheduleAndWakeupMappedQ();
    updateRRVars(nextALId, nextRLId);
    return true;
}

void
HWScheduler::updateRRVars(uint32_t al_idx, uint32_t rl_idx)
{
    nextALId = (al_idx + 1) % MAX_ACTIVE_QUEUES;
    nextRLId = (rl_idx + 1) % hsaPP->numHWQueues;
}

bool
HWScheduler::unmapQFromRQ()
{
    // Identify the next idle queue, if there is no
    // idle queue, we cannot unmap
    if (!findNextIdleRLQ()) {
        return false;
    }
    removeQCntxt();
    return true;
}

void
HWScheduler::removeQCntxt()
{
    // The nextRLId gives the registered queue that is to be unmapped.
    // We can find the corresponding queue_id from the doorbellPointer
    Addr db_offset =
        hsaPP->getRegdListEntry(nextRLId)->qCntxt.qDesc->doorbellPointer;
    hsaPP->getRegdListEntry(nextRLId)->qCntxt.qDesc = NULL;
    hsaPP->getRegdListEntry(nextRLId)->qCntxt.aqlBuf = NULL;
    // Here, we are unmappping a queue wihtout waiting for the outstanding
    // dependency signal reads to complete. We will discard any outstanding
    // reads and will reset the signal values here.
    hsaPP->getRegdListEntry(nextRLId)->depSignalRdState.discardRead = true;
    hsaPP->getRegdListEntry(nextRLId)->depSignalRdState.resetSigVals();
    uint32_t al_idx = dbMap[db_offset];
    assert(regdListMap[al_idx] == nextRLId);
    // Unmap from regdListMap.
    regdListMap.erase(al_idx);
}

bool
HWScheduler::findNextActiveALQ()
{
    for (int activeQId = 0; activeQId < MAX_ACTIVE_QUEUES; activeQId++) {
        uint32_t al_id = (nextALId + activeQId) % MAX_ACTIVE_QUEUES;
        auto aqlmap_iter = activeList.find(al_id);
        if (aqlmap_iter != activeList.end()) {
            // If this queue is already mapped
            if (regdListMap.find(al_id) != regdListMap.end()) {
                continue;
            } else {
                DPRINTF(HSAPacketProcessor,
                        "Next Active ALQ %d (current %d), max ALQ %d\n",
                         al_id, nextALId, MAX_ACTIVE_QUEUES);
                nextALId = al_id;
                return true;
            }
        }
    }
    return false;
}

bool
HWScheduler::findNextIdleRLQ()
{
    for (int regdQId = 0; regdQId < hsaPP->numHWQueues; regdQId++) {
        uint32_t rl_idx = (nextRLId + regdQId) % hsaPP->numHWQueues;
        if (isRLQIdle(rl_idx)) {
            nextRLId = rl_idx;
            return true;
        }
    }
    return false;
}

// This function could be moved to packet processor
bool
HWScheduler::isRLQIdle(uint32_t rl_idx)
{
    DPRINTF(HSAPacketProcessor,
            "@ %s, analyzing hw queue %d\n", __FUNCTION__, rl_idx);
    HSAQueueDescriptor* qDesc = hsaPP->getRegdListEntry(rl_idx)->qCntxt.qDesc;

    // If there a pending DMA to this registered queue
    // then the queue is not idle
    if (qDesc->dmaInProgress) {
        return false;
    }

    // Since packet completion stage happens only after kernel completion
    // we need to keep the queue mapped till all the outstanding kernels
    // from that queue are finished
    if (hsaPP->inFlightPkts(rl_idx)) {
        return false;
    }

    return true;
}

void
HWScheduler::write(Addr db_addr, uint64_t doorbell_reg)
{
    auto dbmap_iter = dbMap.find(db_addr);
    if (dbmap_iter == dbMap.end()) {
        panic("Writing to a non-existing queue (db_offset %x)", db_addr);
    }
    uint32_t al_idx = dbMap[db_addr];
    // Modify the write pointer
    activeList[al_idx].qDesc->writeIndex = doorbell_reg;
    // If this queue is mapped, then start DMA to fetch the
    // AQL packet
    if (regdListMap.find(al_idx) != regdListMap.end()) {
        hsaPP->getCommandsFromHost(0, regdListMap[al_idx]);
    }
}

void
HWScheduler::unregisterQueue(uint64_t queue_id, int doorbellSize)
{
    Addr db_offset = queue_id * doorbellSize;
    auto dbmap_iter = dbMap.find(db_offset);
    if (dbmap_iter == dbMap.end()) {
        panic("Destroying a non-existing queue (db_offset %x)",
               db_offset);
    }
    uint32_t al_idx = dbMap[db_offset];
    assert(dbMap[db_offset] == dbmap_iter->second);
    if (!activeList[al_idx].qDesc->isEmpty()) {
        // According to HSA runtime specification says, deleting
        // a queue before it is fully processed can lead to undefined
        // behavior and it is the application's responsibility to
        // avoid this situation.
        // Even completion signal is not a sufficient indication for a
        // fully processed queue; for example completion signal may be
        // asserted when a read pointer update is in progress
        warn("Destroying a non-empty queue");
    }
    delete activeList[al_idx].qDesc;
    delete activeList[al_idx].aqlBuf;
    activeList.erase(al_idx);
    // Unmap doorbell from doorbell map
    dbMap.erase(db_offset);
    if (regdListMap.find(al_idx) != regdListMap.end()) {
        uint32_t rl_idx = regdListMap[al_idx];
        hsaPP->getRegdListEntry(rl_idx)->qCntxt.aqlBuf = NULL;
        hsaPP->getRegdListEntry(rl_idx)->qCntxt.qDesc = NULL;
        hsaPP->getRegdListEntry(rl_idx)->depSignalRdState.discardRead = true;
        hsaPP->getRegdListEntry(rl_idx)->depSignalRdState.resetSigVals();
        assert(!hsaPP->getRegdListEntry(rl_idx)->aqlProcessEvent.scheduled());
        regdListMap.erase(al_idx);
        // A registered queue is released, let us try to map
        // a queue to that slot
        contextSwitchQ();
    }
    schedWakeup();
}

} // namespace gem5
