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

#define __STDC_FORMAT_MACROS
#include <cinttypes>
#include "debug/GPUCoalescer.hh"
#include "debug/GPUMem.hh"
#include "debug/GPUReg.hh"
#include "gpu-compute/compute_unit.hh"
#include "gpu-compute/global_memory_pipeline.hh"
#include "gpu-compute/gpu_dyn_inst.hh"
#include "gpu-compute/shader.hh"
#include "gpu-compute/vector_register_file.hh"
#include "gpu-compute/wavefront.hh"

namespace gem5
{

GlobalMemPipeline::GlobalMemPipeline(const ComputeUnitParams &p,
                                     ComputeUnit &cu)
    : computeUnit(cu), _name(cu.name() + ".GlobalMemPipeline"),
      gmQueueSize(p.global_mem_queue_size),
      maxWaveRequests(p.max_wave_requests), inflightStores(0),
      inflightLoads(0), stats(&cu)
{
}

void
GlobalMemPipeline::init()
{
    globalMemSize = computeUnit.shader->globalMemSize;
}

bool
GlobalMemPipeline::coalescerReady(GPUDynInstPtr mp) const
{
    // We require one token from the coalescer's uncoalesced table to
    // proceed
    int token_count = 1;

    // Make sure the vector port has tokens. There is a single pool
    // of tokens so only one port in the vector port needs to be checked.
    // Lane 0 is chosen arbirarily.
    DPRINTF(GPUCoalescer, "Checking for %d tokens\n", token_count);
    if (!mp->computeUnit()->getTokenManager()->haveTokens(token_count)) {
        DPRINTF(GPUCoalescer, "Stalling inst because coalsr is busy!\n");
        return false;
    }

    return true;
}

void
GlobalMemPipeline::acqCoalescerToken(GPUDynInstPtr mp)
{
    // We require one token from the coalescer's uncoalesced table to
    // proceed
    int token_count = 1;

    DPRINTF(GPUCoalescer, "Acquiring %d token(s)\n", token_count);
    assert(mp->computeUnit()->getTokenManager()->haveTokens(token_count));
    mp->computeUnit()->getTokenManager()->acquireTokens(token_count);
}

bool
GlobalMemPipeline::outstandingReqsCheck(GPUDynInstPtr mp) const
{
    // Ensure we haven't exceeded the maximum number of vmem requests
    // for this wavefront
    if ((mp->wavefront()->outstandingReqsRdGm
         + mp->wavefront()->outstandingReqsWrGm) >= maxWaveRequests) {
        return false;
    }

    return true;
}

void
GlobalMemPipeline::exec()
{
    // apply any returned global memory operations
    GPUDynInstPtr m = getNextReadyResp();

    bool accessVrf = true;
    Wavefront *w = nullptr;

    // check the VRF to see if the operands of a load (or load component
    // of an atomic) are accessible
    if (m && (m->isLoad() || m->isAtomicRet())) {
        w = m->wavefront();

        accessVrf = w->computeUnit->vrf[w->simdId]->
            canScheduleWriteOperandsFromLoad(w, m);

    }

    if (m && m->latency.rdy() && computeUnit.glbMemToVrfBus.rdy() &&
        accessVrf && (computeUnit.shader->coissue_return ||
        computeUnit.vectorGlobalMemUnit.rdy())) {

        w = m->wavefront();

        DPRINTF(GPUMem, "CU%d: WF[%d][%d]: Completing global mem instr %s\n",
                m->cu_id, m->simdId, m->wfSlotId, m->disassemble());
        m->completeAcc(m);
        if (m->isFlat()) {
            w->decLGKMInstsIssued();
        }
        w->decVMemInstsIssued();

        if (m->isLoad() || m->isAtomicRet()) {
            w->computeUnit->vrf[w->simdId]->
            scheduleWriteOperandsFromLoad(w, m);
        }

        completeRequest(m);

        Tick accessTime = curTick() - m->getAccessTime();

        // Decrement outstanding requests count
        computeUnit.shader->ScheduleAdd(&w->outstandingReqs, m->time, -1);
        if (m->isStore() || m->isAtomic() || m->isMemSync()) {
            computeUnit.shader->sampleStore(accessTime);
            computeUnit.shader->ScheduleAdd(&w->outstandingReqsWrGm,
                                             m->time, -1);
        }

        if (m->isLoad() || m->isAtomic() || m->isMemSync()) {
            computeUnit.shader->sampleLoad(accessTime);
            computeUnit.shader->ScheduleAdd(&w->outstandingReqsRdGm,
                                             m->time, -1);
        }

        w->validateRequestCounters();

        // Generate stats for round-trip time for vectory memory insts
        // going all the way to memory and stats for individual cache
        // blocks generated by the instruction.
        m->profileRoundTripTime(curTick(), InstMemoryHop::Complete);
        computeUnit.shader->sampleInstRoundTrip(m->getRoundTripTime());
        computeUnit.shader->sampleLineRoundTrip(m->getLineAddressTime());

        // Mark write bus busy for appropriate amount of time
        computeUnit.glbMemToVrfBus.set(m->time);
        if (!computeUnit.shader->coissue_return)
            w->computeUnit->vectorGlobalMemUnit.set(m->time);
    }

    // If pipeline has executed a global memory instruction
    // execute global memory packets and issue global
    // memory packets to DTLB
    if (!gmIssuedRequests.empty()) {
        GPUDynInstPtr mp = gmIssuedRequests.front();
        if (mp->isLoad() || mp->isAtomic()) {
            if (inflightLoads >= gmQueueSize) {
                return;
            } else {
                ++inflightLoads;
            }
        } else if (mp->isStore()) {
            if (inflightStores >= gmQueueSize) {
                return;
            } else {
                ++inflightStores;
            }
        }

        DPRINTF(GPUCoalescer, "initiateAcc for %s seqNum %d\n",
                mp->disassemble(), mp->seqNum());
        mp->initiateAcc(mp);

        if (mp->isStore() && mp->isGlobalSeg()) {
            mp->wavefront()->decExpInstsIssued();
        }

        if (((mp->isMemSync() && !mp->isEndOfKernel()) || !mp->isMemSync())) {
            /**
             * if we are not in out-of-order data delivery mode
             * then we keep the responses sorted in program order.
             * in order to do so we must reserve an entry in the
             * resp buffer before we issue the request to the mem
             * system. mem fence requests will not be stored here
             * because once they are issued from the GM pipeline,
             * they do not send any response back to it.
             */
            gmOrderedRespBuffer.insert(std::make_pair(mp->seqNum(),
                std::make_pair(mp, false)));
        }

        if (!mp->isMemSync() && !mp->isEndOfKernel() && mp->allLanesZero()) {
            /**
            * Memory accesses instructions that do not generate any memory
            * requests (such as out-of-bounds buffer acceses where all lanes
            * are out of bounds) will not trigger a callback to complete the
            * request, so we need to mark it as completed as soon as it is
            * issued.  Note this this will still insert an entry in the
            * ordered return FIFO such that waitcnt is still resolved
            * correctly.
            */
            handleResponse(mp);
            computeUnit.getTokenManager()->recvTokens(1);
        }

        gmIssuedRequests.pop();

        DPRINTF(GPUMem, "CU%d: WF[%d][%d] Popping 0 mem_op = \n",
                computeUnit.cu_id, mp->simdId, mp->wfSlotId);
    }
}

GPUDynInstPtr
GlobalMemPipeline::getNextReadyResp()
{
    if (!gmOrderedRespBuffer.empty()) {
        auto mem_req = gmOrderedRespBuffer.begin();

        if (mem_req->second.second) {
            return mem_req->second.first;
        }
    }

    return nullptr;
}

void
GlobalMemPipeline::completeRequest(GPUDynInstPtr gpuDynInst)
{
    if (gpuDynInst->isLoad() || gpuDynInst->isAtomic()) {
        assert(inflightLoads > 0);
        --inflightLoads;
    } else if (gpuDynInst->isStore()) {
        assert(inflightStores > 0);
        --inflightStores;
    }

    // we should only pop the oldest requst, and it
    // should be marked as done if we are here
    assert(gmOrderedRespBuffer.begin()->first == gpuDynInst->seqNum());
    assert(gmOrderedRespBuffer.begin()->second.first == gpuDynInst);
    assert(gmOrderedRespBuffer.begin()->second.second);
    // remove this instruction from the buffer by its
    // unique seq ID
    gmOrderedRespBuffer.erase(gpuDynInst->seqNum());
}

void
GlobalMemPipeline::issueRequest(GPUDynInstPtr gpuDynInst)
{
    Wavefront *wf = gpuDynInst->wavefront();
    if (gpuDynInst->isLoad()) {
        wf->rdGmReqsInPipe--;
        wf->outstandingReqsRdGm++;
    } else if (gpuDynInst->isStore()) {
        wf->wrGmReqsInPipe--;
        wf->outstandingReqsWrGm++;
    } else {
        // Atomic, both read and write
        wf->rdGmReqsInPipe--;
        wf->outstandingReqsRdGm++;
        wf->wrGmReqsInPipe--;
        wf->outstandingReqsWrGm++;
    }

    wf->outstandingReqs++;
    wf->validateRequestCounters();

    gpuDynInst->setAccessTime(curTick());
    gpuDynInst->profileRoundTripTime(curTick(), InstMemoryHop::Initiate);
    gmIssuedRequests.push(gpuDynInst);
}

void
GlobalMemPipeline::handleResponse(GPUDynInstPtr gpuDynInst)
{
    auto mem_req = gmOrderedRespBuffer.find(gpuDynInst->seqNum());
    // if we are getting a response for this mem request,
    // then it ought to already be in the ordered response
    // buffer
    assert(mem_req != gmOrderedRespBuffer.end());
    mem_req->second.second = true;
}

GlobalMemPipeline::
GlobalMemPipelineStats::GlobalMemPipelineStats(statistics::Group *parent)
    : statistics::Group(parent, "GlobalMemPipeline"),
      ADD_STAT(loadVrfBankConflictCycles, "total number of cycles GM data "
               "are delayed before updating the VRF")
{
}

} // namespace gem5
