/*
 * 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.
 *
 * Authors: Mark Wyse
 */

#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"

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]);

    int endIndex = (w->startVgprIndex + w->reservedVectorRegs - 1) %
        w->computeUnit->vrf[w->simdId]->numRegs();

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

    // mark/pre-mark all registers as 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 - 1) %
        w->computeUnit->srf[w->simdId]->numRegs();
    w->computeUnit->registerManager.srfPoolMgrs[w->simdId]->
        freeRegion(w->startSgprIndex, endIndex);

    // mark/pre-mark all registers as 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;
}

void
StaticRegisterManagerPolicy::regStats()
{
}
