/*
 * 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()
{
}
