blob: cc32abe441c0d39c7da46e645482ac3a143440fa [file] [log] [blame]
/*
* 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