/*
 * Copyright (c) 2016 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 "gpu-compute/static_register_manager_policy.hh"

#include "config/the_gpu_isa.hh"
#include "debug/GPURename.hh"
#include "gpu-compute/compute_unit.hh"
#include "gpu-compute/pool_manager.hh"
#include "gpu-compute/scalar_register_file.hh"
#include "gpu-compute/shader.hh"
#include "gpu-compute/vector_register_file.hh"
#include "gpu-compute/wavefront.hh"

namespace gem5
{

StaticRegisterManagerPolicy::StaticRegisterManagerPolicy()
{
}

void
StaticRegisterManagerPolicy::exec()
{
}

int
StaticRegisterManagerPolicy::mapVgpr(Wavefront* w, int vgprIndex)
{
    panic_if((vgprIndex >= w->reservedVectorRegs)
             || (w->reservedVectorRegs < 0),
             "VGPR index %d is out of range: VGPR range=[0,%d]",
             vgprIndex, w->reservedVectorRegs);

    // add the offset from where the VGPRs of the wavefront have been assigned
    int physicalVgprIndex = w->startVgprIndex + vgprIndex;

    panic_if(!((w->startVgprIndex <= physicalVgprIndex) &&
             (w->startVgprIndex + w->reservedVectorRegs - 1)
             >= physicalVgprIndex),
             "Invalid VGPR index %d\n", physicalVgprIndex);

    // calculate physical VGPR index
    return physicalVgprIndex % w->computeUnit->vrf[w->simdId]->numRegs();
}

int
StaticRegisterManagerPolicy::mapSgpr(Wavefront* w, int sgprIndex)
{
    panic_if(!((sgprIndex < w->reservedScalarRegs)
             && (w->reservedScalarRegs > 0)),
             "SGPR index %d is out of range: SGPR range=[0,%d]\n",
             sgprIndex, w->reservedScalarRegs);

    // add the offset from where the SGPRs of the wavefront have been assigned
    int physicalSgprIndex = w->startSgprIndex + sgprIndex;

    panic_if(!((w->startSgprIndex <= physicalSgprIndex) &&
             (w->startSgprIndex + w->reservedScalarRegs - 1)
             >= physicalSgprIndex),
             "Invalid SGPR index %d\n", physicalSgprIndex);

    // calculate physical SGPR index
    return physicalSgprIndex % w->computeUnit->srf[w->simdId]->numRegs();
}

bool
StaticRegisterManagerPolicy::canAllocateVgprs(int simdId, int nWfs,
                                              int demandPerWf)
{
    return cu->registerManager->vrfPoolMgrs[simdId]->
        canAllocate(nWfs, demandPerWf);
}

bool
StaticRegisterManagerPolicy::canAllocateSgprs(int simdId, int nWfs,
                                              int demandPerWf)
{
    return cu->registerManager->srfPoolMgrs[simdId]->
        canAllocate(nWfs, demandPerWf);
}

void
StaticRegisterManagerPolicy::allocateRegisters(Wavefront *w, int vectorDemand,
                                               int scalarDemand)
{
    uint32_t allocatedSize = 0;
    w->startVgprIndex = cu->registerManager->vrfPoolMgrs[w->simdId]->
        allocateRegion(vectorDemand, &allocatedSize);
    w->reservedVectorRegs = allocatedSize;
    cu->vectorRegsReserved[w->simdId] += w->reservedVectorRegs;
    panic_if(cu->vectorRegsReserved[w->simdId] > cu->numVecRegsPerSimd,
             "VRF[%d] has been overallocated %d > %d\n",
             w->simdId, cu->vectorRegsReserved[w->simdId],
             cu->numVecRegsPerSimd);

    if (scalarDemand) {
        w->startSgprIndex = cu->registerManager->srfPoolMgrs[w->simdId]->
            allocateRegion(scalarDemand, &allocatedSize);
        w->reservedScalarRegs = allocatedSize;
        cu->scalarRegsReserved[w->simdId] += w->reservedScalarRegs;
        panic_if(cu->scalarRegsReserved[w->simdId] > cu->numScalarRegsPerSimd,
                 "SRF[%d] has been overallocated %d > %d\n",
                 w->simdId, cu->scalarRegsReserved[w->simdId],
                 cu->numScalarRegsPerSimd);
    }
}

void
StaticRegisterManagerPolicy::freeRegisters(Wavefront *w)
{
    // free the vector registers of the completed wavefront
    w->computeUnit->vectorRegsReserved[w->simdId] -= w->reservedVectorRegs;
    // free the scalar registers of the completed wavefront
    w->computeUnit->scalarRegsReserved[w->simdId] -= w->reservedScalarRegs;

    panic_if(w->computeUnit->vectorRegsReserved[w->simdId] < 0,
             "Freeing VRF[%d] registers left %d registers reserved\n",
             w->simdId,
             w->computeUnit->vectorRegsReserved[w->simdId]);
    panic_if(w->computeUnit->scalarRegsReserved[w->simdId] < 0,
             "Freeing SRF[%d] registers left %d registers reserved\n",
             w->simdId,
             w->computeUnit->scalarRegsReserved[w->simdId]);

    // Current dynamic register allocation does not handle wraparound
    int endIndex = w->startVgprIndex + w->reservedVectorRegs;

    w->computeUnit->registerManager->vrfPoolMgrs[w->simdId]->
        freeRegion(w->startVgprIndex, endIndex);

    // mark/pre-mark all registers are not busy
    for (int i = 0; i < w->reservedVectorRegs; i++) {
        uint32_t physVgprIdx = mapVgpr(w, i);
        w->computeUnit->vrf[w->simdId]->markReg(physVgprIdx, false);
    }

    w->reservedVectorRegs = 0;
    w->startVgprIndex = 0;

    endIndex = w->startSgprIndex + w->reservedScalarRegs;
    w->computeUnit->registerManager->srfPoolMgrs[w->simdId]->
        freeRegion(w->startSgprIndex, endIndex);

    // mark/pre-mark all registers are not busy
    for (int i = 0; i < w->reservedScalarRegs; i++) {
        uint32_t physSgprIdx = mapSgpr(w, i);
        w->computeUnit->srf[w->simdId]->markReg(physSgprIdx, false);
    }

    w->reservedScalarRegs = 0;
    w->startSgprIndex = 0;
}

} // namespace gem5
