111308Santhony.gutierrez@amd.com/*
212697Santhony.gutierrez@amd.com * Copyright (c) 2015-2017 Advanced Micro Devices, Inc.
311308Santhony.gutierrez@amd.com * All rights reserved.
411308Santhony.gutierrez@amd.com *
511308Santhony.gutierrez@amd.com * For use for simulation and test purposes only
611308Santhony.gutierrez@amd.com *
711308Santhony.gutierrez@amd.com * Redistribution and use in source and binary forms, with or without
811308Santhony.gutierrez@amd.com * modification, are permitted provided that the following conditions are met:
911308Santhony.gutierrez@amd.com *
1011308Santhony.gutierrez@amd.com * 1. Redistributions of source code must retain the above copyright notice,
1111308Santhony.gutierrez@amd.com * this list of conditions and the following disclaimer.
1211308Santhony.gutierrez@amd.com *
1311308Santhony.gutierrez@amd.com * 2. Redistributions in binary form must reproduce the above copyright notice,
1411308Santhony.gutierrez@amd.com * this list of conditions and the following disclaimer in the documentation
1511308Santhony.gutierrez@amd.com * and/or other materials provided with the distribution.
1611308Santhony.gutierrez@amd.com *
1712697Santhony.gutierrez@amd.com * 3. Neither the name of the copyright holder nor the names of its
1812697Santhony.gutierrez@amd.com * contributors may be used to endorse or promote products derived from this
1912697Santhony.gutierrez@amd.com * software without specific prior written permission.
2011308Santhony.gutierrez@amd.com *
2111308Santhony.gutierrez@amd.com * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
2211308Santhony.gutierrez@amd.com * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
2311308Santhony.gutierrez@amd.com * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
2411308Santhony.gutierrez@amd.com * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
2511308Santhony.gutierrez@amd.com * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
2611308Santhony.gutierrez@amd.com * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
2711308Santhony.gutierrez@amd.com * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
2811308Santhony.gutierrez@amd.com * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
2911308Santhony.gutierrez@amd.com * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
3011308Santhony.gutierrez@amd.com * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
3111308Santhony.gutierrez@amd.com * POSSIBILITY OF SUCH DAMAGE.
3211308Santhony.gutierrez@amd.com *
3312697Santhony.gutierrez@amd.com * Authors: John Kalamatianos,
3412697Santhony.gutierrez@amd.com *          Mark Wyse
3511308Santhony.gutierrez@amd.com */
3611308Santhony.gutierrez@amd.com
3711308Santhony.gutierrez@amd.com#include "gpu-compute/vector_register_file.hh"
3811308Santhony.gutierrez@amd.com
3911308Santhony.gutierrez@amd.com#include <string>
4011308Santhony.gutierrez@amd.com
4112334Sgabeblack@google.com#include "base/logging.hh"
4211308Santhony.gutierrez@amd.com#include "gpu-compute/compute_unit.hh"
4311308Santhony.gutierrez@amd.com#include "gpu-compute/gpu_dyn_inst.hh"
4411308Santhony.gutierrez@amd.com#include "gpu-compute/shader.hh"
4511308Santhony.gutierrez@amd.com#include "gpu-compute/simple_pool_manager.hh"
4611308Santhony.gutierrez@amd.com#include "gpu-compute/wavefront.hh"
4711308Santhony.gutierrez@amd.com#include "params/VectorRegisterFile.hh"
4811308Santhony.gutierrez@amd.com
4911308Santhony.gutierrez@amd.comVectorRegisterFile::VectorRegisterFile(const VectorRegisterFileParams *p)
5011308Santhony.gutierrez@amd.com    : SimObject(p),
5111308Santhony.gutierrez@amd.com      manager(new SimplePoolManager(p->min_alloc, p->num_regs_per_simd)),
5211308Santhony.gutierrez@amd.com      simdId(p->simd_id), numRegsPerSimd(p->num_regs_per_simd),
5311308Santhony.gutierrez@amd.com      vgprState(new VecRegisterState())
5411308Santhony.gutierrez@amd.com{
5511308Santhony.gutierrez@amd.com    fatal_if(numRegsPerSimd % 2, "VRF size is illegal\n");
5611308Santhony.gutierrez@amd.com    fatal_if(simdId < 0, "Illegal SIMD id for VRF");
5711308Santhony.gutierrez@amd.com
5811308Santhony.gutierrez@amd.com    fatal_if(numRegsPerSimd % p->min_alloc, "Min VGPR region allocation is not "
5911308Santhony.gutierrez@amd.com             "multiple of VRF size\n");
6011308Santhony.gutierrez@amd.com
6111308Santhony.gutierrez@amd.com    busy.clear();
6211308Santhony.gutierrez@amd.com    busy.resize(numRegsPerSimd, 0);
6311308Santhony.gutierrez@amd.com    nxtBusy.clear();
6411308Santhony.gutierrez@amd.com    nxtBusy.resize(numRegsPerSimd, 0);
6511308Santhony.gutierrez@amd.com
6611534Sjohn.kalamatianos@amd.com    vgprState->init(numRegsPerSimd, p->wfSize);
6711308Santhony.gutierrez@amd.com}
6811308Santhony.gutierrez@amd.com
6911308Santhony.gutierrez@amd.comvoid
7011308Santhony.gutierrez@amd.comVectorRegisterFile::setParent(ComputeUnit *_computeUnit)
7111308Santhony.gutierrez@amd.com{
7211308Santhony.gutierrez@amd.com    computeUnit = _computeUnit;
7311308Santhony.gutierrez@amd.com    vgprState->setParent(computeUnit);
7411308Santhony.gutierrez@amd.com}
7511308Santhony.gutierrez@amd.com
7611308Santhony.gutierrez@amd.comuint8_t
7711308Santhony.gutierrez@amd.comVectorRegisterFile::regNxtBusy(int idx, uint32_t operandSize) const
7811308Santhony.gutierrez@amd.com{
7911308Santhony.gutierrez@amd.com    uint8_t status = nxtBusy.at(idx);
8011308Santhony.gutierrez@amd.com
8111308Santhony.gutierrez@amd.com    if (operandSize > 4) {
8211308Santhony.gutierrez@amd.com        status = status | (nxtBusy.at((idx + 1) % numRegs()));
8311308Santhony.gutierrez@amd.com    }
8411308Santhony.gutierrez@amd.com
8511308Santhony.gutierrez@amd.com    return status;
8611308Santhony.gutierrez@amd.com}
8711308Santhony.gutierrez@amd.com
8811308Santhony.gutierrez@amd.comuint8_t
8911308Santhony.gutierrez@amd.comVectorRegisterFile::regBusy(int idx, uint32_t operandSize) const
9011308Santhony.gutierrez@amd.com{
9111308Santhony.gutierrez@amd.com    uint8_t status = busy.at(idx);
9211308Santhony.gutierrez@amd.com
9311308Santhony.gutierrez@amd.com    if (operandSize > 4) {
9411308Santhony.gutierrez@amd.com        status = status | (busy.at((idx + 1) % numRegs()));
9511308Santhony.gutierrez@amd.com    }
9611308Santhony.gutierrez@amd.com
9711308Santhony.gutierrez@amd.com    return status;
9811308Santhony.gutierrez@amd.com}
9911308Santhony.gutierrez@amd.com
10011308Santhony.gutierrez@amd.comvoid
10111308Santhony.gutierrez@amd.comVectorRegisterFile::preMarkReg(int regIdx, uint32_t operandSize, uint8_t value)
10211308Santhony.gutierrez@amd.com{
10311308Santhony.gutierrez@amd.com    nxtBusy.at(regIdx) = value;
10411308Santhony.gutierrez@amd.com
10511308Santhony.gutierrez@amd.com    if (operandSize > 4) {
10611308Santhony.gutierrez@amd.com        nxtBusy.at((regIdx + 1) % numRegs()) = value;
10711308Santhony.gutierrez@amd.com    }
10811308Santhony.gutierrez@amd.com}
10911308Santhony.gutierrez@amd.com
11011308Santhony.gutierrez@amd.comvoid
11111308Santhony.gutierrez@amd.comVectorRegisterFile::markReg(int regIdx, uint32_t operandSize, uint8_t value)
11211308Santhony.gutierrez@amd.com{
11311308Santhony.gutierrez@amd.com    busy.at(regIdx) = value;
11411308Santhony.gutierrez@amd.com
11511308Santhony.gutierrez@amd.com    if (operandSize > 4) {
11611308Santhony.gutierrez@amd.com        busy.at((regIdx + 1) % numRegs()) = value;
11711308Santhony.gutierrez@amd.com    }
11811308Santhony.gutierrez@amd.com}
11911308Santhony.gutierrez@amd.com
12011308Santhony.gutierrez@amd.combool
12111308Santhony.gutierrez@amd.comVectorRegisterFile::operandsReady(Wavefront *w, GPUDynInstPtr ii) const
12211308Santhony.gutierrez@amd.com{
12311308Santhony.gutierrez@amd.com    for (int i = 0; i < ii->getNumOperands(); ++i) {
12411308Santhony.gutierrez@amd.com        if (ii->isVectorRegister(i)) {
12511699Santhony.gutierrez@amd.com            uint32_t vgprIdx = ii->getRegisterIndex(i, ii);
12611308Santhony.gutierrez@amd.com            uint32_t pVgpr = w->remap(vgprIdx, ii->getOperandSize(i), 1);
12711308Santhony.gutierrez@amd.com
12811308Santhony.gutierrez@amd.com            if (regBusy(pVgpr, ii->getOperandSize(i)) == 1) {
12911308Santhony.gutierrez@amd.com                if (ii->isDstOperand(i)) {
13011308Santhony.gutierrez@amd.com                    w->numTimesBlockedDueWAXDependencies++;
13111308Santhony.gutierrez@amd.com                } else if (ii->isSrcOperand(i)) {
13211308Santhony.gutierrez@amd.com                    w->numTimesBlockedDueRAWDependencies++;
13311308Santhony.gutierrez@amd.com                }
13411308Santhony.gutierrez@amd.com
13511308Santhony.gutierrez@amd.com                return false;
13611308Santhony.gutierrez@amd.com            }
13711308Santhony.gutierrez@amd.com
13811308Santhony.gutierrez@amd.com            if (regNxtBusy(pVgpr, ii->getOperandSize(i)) == 1) {
13911308Santhony.gutierrez@amd.com                if (ii->isDstOperand(i)) {
14011308Santhony.gutierrez@amd.com                    w->numTimesBlockedDueWAXDependencies++;
14111308Santhony.gutierrez@amd.com                } else if (ii->isSrcOperand(i)) {
14211308Santhony.gutierrez@amd.com                    w->numTimesBlockedDueRAWDependencies++;
14311308Santhony.gutierrez@amd.com                }
14411308Santhony.gutierrez@amd.com
14511308Santhony.gutierrez@amd.com                return false;
14611308Santhony.gutierrez@amd.com            }
14711308Santhony.gutierrez@amd.com        }
14811308Santhony.gutierrez@amd.com    }
14911308Santhony.gutierrez@amd.com
15011308Santhony.gutierrez@amd.com    return true;
15111308Santhony.gutierrez@amd.com}
15211308Santhony.gutierrez@amd.com
15311308Santhony.gutierrez@amd.comvoid
15411308Santhony.gutierrez@amd.comVectorRegisterFile::exec(GPUDynInstPtr ii, Wavefront *w)
15511308Santhony.gutierrez@amd.com{
15611692Santhony.gutierrez@amd.com    bool loadInstr = ii->isLoad();
15711692Santhony.gutierrez@amd.com    bool atomicInstr = ii->isAtomic() || ii->isMemFence();
15811308Santhony.gutierrez@amd.com
15911308Santhony.gutierrez@amd.com    bool loadNoArgInstr = loadInstr && !ii->isArgLoad();
16011308Santhony.gutierrez@amd.com
16111308Santhony.gutierrez@amd.com    // iterate over all register destination operands
16211308Santhony.gutierrez@amd.com    for (int i = 0; i < ii->getNumOperands(); ++i) {
16311308Santhony.gutierrez@amd.com        if (ii->isVectorRegister(i) && ii->isDstOperand(i)) {
16411699Santhony.gutierrez@amd.com            uint32_t physReg = w->remap(ii->getRegisterIndex(i, ii),
16511308Santhony.gutierrez@amd.com                                        ii->getOperandSize(i), 1);
16611308Santhony.gutierrez@amd.com
16711308Santhony.gutierrez@amd.com            // mark the destination vector register as busy
16811308Santhony.gutierrez@amd.com            markReg(physReg, ii->getOperandSize(i), 1);
16911308Santhony.gutierrez@amd.com            // clear the in-flight status of the destination vector register
17011308Santhony.gutierrez@amd.com            preMarkReg(physReg, ii->getOperandSize(i), 0);
17111308Santhony.gutierrez@amd.com
17211308Santhony.gutierrez@amd.com            // FIXME: if we ever model correct timing behavior
17311308Santhony.gutierrez@amd.com            // for load argument instructions then we should not
17411308Santhony.gutierrez@amd.com            // set the destination register as busy now but when
17511308Santhony.gutierrez@amd.com            // the data returns. Loads and Atomics should free
17611308Santhony.gutierrez@amd.com            // their destination registers when the data returns,
17711308Santhony.gutierrez@amd.com            // not now
17811308Santhony.gutierrez@amd.com            if (!atomicInstr && !loadNoArgInstr) {
17911308Santhony.gutierrez@amd.com                uint32_t pipeLen = ii->getOperandSize(i) <= 4 ?
18011308Santhony.gutierrez@amd.com                    computeUnit->spBypassLength() :
18111308Santhony.gutierrez@amd.com                    computeUnit->dpBypassLength();
18211308Santhony.gutierrez@amd.com
18311308Santhony.gutierrez@amd.com                // schedule an event for marking the register as ready
18411308Santhony.gutierrez@amd.com                computeUnit->registerEvent(w->simdId, physReg,
18511308Santhony.gutierrez@amd.com                                           ii->getOperandSize(i),
18611308Santhony.gutierrez@amd.com                                           computeUnit->shader->tick_cnt +
18711308Santhony.gutierrez@amd.com                                           computeUnit->shader->ticks(pipeLen),
18811308Santhony.gutierrez@amd.com                                           0);
18911308Santhony.gutierrez@amd.com            }
19011308Santhony.gutierrez@amd.com        }
19111308Santhony.gutierrez@amd.com    }
19211308Santhony.gutierrez@amd.com}
19311308Santhony.gutierrez@amd.com
19411308Santhony.gutierrez@amd.comint
19511308Santhony.gutierrez@amd.comVectorRegisterFile::exec(uint64_t dynamic_id, Wavefront *w,
19611308Santhony.gutierrez@amd.com                         std::vector<uint32_t> &regVec, uint32_t operandSize,
19711308Santhony.gutierrez@amd.com                         uint64_t timestamp)
19811308Santhony.gutierrez@amd.com{
19911308Santhony.gutierrez@amd.com    int delay = 0;
20011308Santhony.gutierrez@amd.com
20111308Santhony.gutierrez@amd.com    panic_if(regVec.size() <= 0, "Illegal VGPR vector size=%d\n",
20211308Santhony.gutierrez@amd.com             regVec.size());
20311308Santhony.gutierrez@amd.com
20411308Santhony.gutierrez@amd.com    for (int i = 0; i < regVec.size(); ++i) {
20511308Santhony.gutierrez@amd.com        // mark the destination VGPR as free when the timestamp expires
20611308Santhony.gutierrez@amd.com        computeUnit->registerEvent(w->simdId, regVec[i], operandSize,
20711308Santhony.gutierrez@amd.com                                   computeUnit->shader->tick_cnt + timestamp +
20811308Santhony.gutierrez@amd.com                                   computeUnit->shader->ticks(delay), 0);
20911308Santhony.gutierrez@amd.com    }
21011308Santhony.gutierrez@amd.com
21111308Santhony.gutierrez@amd.com    return delay;
21211308Santhony.gutierrez@amd.com}
21311308Santhony.gutierrez@amd.com
21411308Santhony.gutierrez@amd.comvoid
21511308Santhony.gutierrez@amd.comVectorRegisterFile::updateResources(Wavefront *w, GPUDynInstPtr ii)
21611308Santhony.gutierrez@amd.com{
21711308Santhony.gutierrez@amd.com    // iterate over all register destination operands
21811308Santhony.gutierrez@amd.com    for (int i = 0; i < ii->getNumOperands(); ++i) {
21911308Santhony.gutierrez@amd.com        if (ii->isVectorRegister(i) && ii->isDstOperand(i)) {
22011699Santhony.gutierrez@amd.com            uint32_t physReg = w->remap(ii->getRegisterIndex(i, ii),
22111308Santhony.gutierrez@amd.com                                        ii->getOperandSize(i), 1);
22211308Santhony.gutierrez@amd.com            // set the in-flight status of the destination vector register
22311308Santhony.gutierrez@amd.com            preMarkReg(physReg, ii->getOperandSize(i), 1);
22411308Santhony.gutierrez@amd.com        }
22511308Santhony.gutierrez@amd.com    }
22611308Santhony.gutierrez@amd.com}
22711308Santhony.gutierrez@amd.com
22811308Santhony.gutierrez@amd.combool
22911308Santhony.gutierrez@amd.comVectorRegisterFile::vrfOperandAccessReady(uint64_t dynamic_id, Wavefront *w,
23011308Santhony.gutierrez@amd.com                                          GPUDynInstPtr ii,
23111308Santhony.gutierrez@amd.com                                          VrfAccessType accessType)
23211308Santhony.gutierrez@amd.com{
23311308Santhony.gutierrez@amd.com    bool ready = true;
23411308Santhony.gutierrez@amd.com
23511308Santhony.gutierrez@amd.com    return ready;
23611308Santhony.gutierrez@amd.com}
23711308Santhony.gutierrez@amd.com
23811308Santhony.gutierrez@amd.combool
23911308Santhony.gutierrez@amd.comVectorRegisterFile::vrfOperandAccessReady(Wavefront *w, GPUDynInstPtr ii,
24011308Santhony.gutierrez@amd.com                                          VrfAccessType accessType)
24111308Santhony.gutierrez@amd.com{
24211308Santhony.gutierrez@amd.com    bool ready = true;
24311308Santhony.gutierrez@amd.com
24411308Santhony.gutierrez@amd.com    return ready;
24511308Santhony.gutierrez@amd.com}
24611308Santhony.gutierrez@amd.com
24711308Santhony.gutierrez@amd.comVectorRegisterFile*
24811308Santhony.gutierrez@amd.comVectorRegisterFileParams::create()
24911308Santhony.gutierrez@amd.com{
25011308Santhony.gutierrez@amd.com    return new VectorRegisterFile(this);
25111308Santhony.gutierrez@amd.com}
252