2 * Copyright (c) 2015 Advanced Micro Devices, Inc.
5 * For use for simulation and test purposes only
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions are met:
10 * 1. Redistributions of source code must retain the above copyright notice,
11 * this list of conditions and the following disclaimer.
13 * 2. Redistributions in binary form must reproduce the above copyright notice,
14 * this list of conditions and the following disclaimer in the documentation
15 * and/or other materials provided with the distribution.
17 * 3. Neither the name of the copyright holder nor the names of its contributors
18 * may be used to endorse or promote products derived from this software
19 * without specific prior written permission.
21 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
22 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
23 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
24 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
25 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
26 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
27 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
28 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
29 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
30 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
31 * POSSIBILITY OF SUCH DAMAGE.
33 * Author: John Kalamatianos
36 #include "gpu-compute/vector_register_file.hh"
40 #include "base/misc.hh"
41 #include "gpu-compute/code_enums.hh"
42 #include "gpu-compute/compute_unit.hh"
43 #include "gpu-compute/gpu_dyn_inst.hh"
44 #include "gpu-compute/shader.hh"
45 #include "gpu-compute/simple_pool_manager.hh"
46 #include "gpu-compute/wavefront.hh"
47 #include "params/VectorRegisterFile.hh"
49 VectorRegisterFile::VectorRegisterFile(const VectorRegisterFileParams
*p
)
51 manager(new SimplePoolManager(p
->min_alloc
, p
->num_regs_per_simd
)),
52 simdId(p
->simd_id
), numRegsPerSimd(p
->num_regs_per_simd
),
53 vgprState(new VecRegisterState())
55 fatal_if(numRegsPerSimd
% 2, "VRF size is illegal\n");
56 fatal_if(simdId
< 0, "Illegal SIMD id for VRF");
58 fatal_if(numRegsPerSimd
% p
->min_alloc
, "Min VGPR region allocation is not "
59 "multiple of VRF size\n");
62 busy
.resize(numRegsPerSimd
, 0);
64 nxtBusy
.resize(numRegsPerSimd
, 0);
66 vgprState
->init(numRegsPerSimd
, p
->wfSize
);
70 VectorRegisterFile::setParent(ComputeUnit
*_computeUnit
)
72 computeUnit
= _computeUnit
;
73 vgprState
->setParent(computeUnit
);
77 VectorRegisterFile::regNxtBusy(int idx
, uint32_t operandSize
) const
79 uint8_t status
= nxtBusy
.at(idx
);
81 if (operandSize
> 4) {
82 status
= status
| (nxtBusy
.at((idx
+ 1) % numRegs()));
89 VectorRegisterFile::regBusy(int idx
, uint32_t operandSize
) const
91 uint8_t status
= busy
.at(idx
);
93 if (operandSize
> 4) {
94 status
= status
| (busy
.at((idx
+ 1) % numRegs()));
101 VectorRegisterFile::preMarkReg(int regIdx
, uint32_t operandSize
, uint8_t value
)
103 nxtBusy
.at(regIdx
) = value
;
105 if (operandSize
> 4) {
106 nxtBusy
.at((regIdx
+ 1) % numRegs()) = value
;
111 VectorRegisterFile::markReg(int regIdx
, uint32_t operandSize
, uint8_t value
)
113 busy
.at(regIdx
) = value
;
115 if (operandSize
> 4) {
116 busy
.at((regIdx
+ 1) % numRegs()) = value
;
121 VectorRegisterFile::operandsReady(Wavefront
*w
, GPUDynInstPtr ii
) const
123 for (int i
= 0; i
< ii
->getNumOperands(); ++i
) {
124 if (ii
->isVectorRegister(i
)) {
125 uint32_t vgprIdx
= ii
->getRegisterIndex(i
);
126 uint32_t pVgpr
= w
->remap(vgprIdx
, ii
->getOperandSize(i
), 1);
128 if (regBusy(pVgpr
, ii
->getOperandSize(i
)) == 1) {
129 if (ii
->isDstOperand(i
)) {
130 w
->numTimesBlockedDueWAXDependencies
++;
131 } else if (ii
->isSrcOperand(i
)) {
132 w
->numTimesBlockedDueRAWDependencies
++;
138 if (regNxtBusy(pVgpr
, ii
->getOperandSize(i
)) == 1) {
139 if (ii
->isDstOperand(i
)) {
140 w
->numTimesBlockedDueWAXDependencies
++;
141 } else if (ii
->isSrcOperand(i
)) {
142 w
->numTimesBlockedDueRAWDependencies
++;
154 VectorRegisterFile::exec(GPUDynInstPtr ii
, Wavefront
*w
)
156 bool loadInstr
= IS_OT_READ(ii
->opType());
157 bool atomicInstr
= IS_OT_ATOMIC(ii
->opType());
159 bool loadNoArgInstr
= loadInstr
&& !ii
->isArgLoad();
161 // iterate over all register destination operands
162 for (int i
= 0; i
< ii
->getNumOperands(); ++i
) {
163 if (ii
->isVectorRegister(i
) && ii
->isDstOperand(i
)) {
164 uint32_t physReg
= w
->remap(ii
->getRegisterIndex(i
),
165 ii
->getOperandSize(i
), 1);
167 // mark the destination vector register as busy
168 markReg(physReg
, ii
->getOperandSize(i
), 1);
169 // clear the in-flight status of the destination vector register
170 preMarkReg(physReg
, ii
->getOperandSize(i
), 0);
172 // FIXME: if we ever model correct timing behavior
173 // for load argument instructions then we should not
174 // set the destination register as busy now but when
175 // the data returns. Loads and Atomics should free
176 // their destination registers when the data returns,
178 if (!atomicInstr
&& !loadNoArgInstr
) {
179 uint32_t pipeLen
= ii
->getOperandSize(i
) <= 4 ?
180 computeUnit
->spBypassLength() :
181 computeUnit
->dpBypassLength();
183 // schedule an event for marking the register as ready
184 computeUnit
->registerEvent(w
->simdId
, physReg
,
185 ii
->getOperandSize(i
),
186 computeUnit
->shader
->tick_cnt
+
187 computeUnit
->shader
->ticks(pipeLen
),
195 VectorRegisterFile::exec(uint64_t dynamic_id
, Wavefront
*w
,
196 std::vector
<uint32_t> ®Vec
, uint32_t operandSize
,
201 panic_if(regVec
.size() <= 0, "Illegal VGPR vector size=%d\n",
204 for (int i
= 0; i
< regVec
.size(); ++i
) {
205 // mark the destination VGPR as free when the timestamp expires
206 computeUnit
->registerEvent(w
->simdId
, regVec
[i
], operandSize
,
207 computeUnit
->shader
->tick_cnt
+ timestamp
+
208 computeUnit
->shader
->ticks(delay
), 0);
215 VectorRegisterFile::updateResources(Wavefront
*w
, GPUDynInstPtr ii
)
217 // iterate over all register destination operands
218 for (int i
= 0; i
< ii
->getNumOperands(); ++i
) {
219 if (ii
->isVectorRegister(i
) && ii
->isDstOperand(i
)) {
220 uint32_t physReg
= w
->remap(ii
->getRegisterIndex(i
),
221 ii
->getOperandSize(i
), 1);
222 // set the in-flight status of the destination vector register
223 preMarkReg(physReg
, ii
->getOperandSize(i
), 1);
229 VectorRegisterFile::vrfOperandAccessReady(uint64_t dynamic_id
, Wavefront
*w
,
231 VrfAccessType accessType
)
239 VectorRegisterFile::vrfOperandAccessReady(Wavefront
*w
, GPUDynInstPtr ii
,
240 VrfAccessType accessType
)
248 VectorRegisterFileParams::create()
250 return new VectorRegisterFile(this);