1/*
2 * Copyright (c) 2014-2015 Advanced Micro Devices, Inc.
3 * All rights reserved.
4 *
5 * For use for simulation and test purposes only
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions are met:
9 *
10 * 1. Redistributions of source code must retain the above copyright notice,
11 * this list of conditions and the following disclaimer.
12 *
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.
16 *
17 * 3. Neither the name of the copyright holder nor the names of its
18 * contributors may be used to endorse or promote products derived from this
19 * software without specific prior written permission.
20 *
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.
32 *
33 * Authors: John Kalamatianos,
34 *          Sooraj Puthoor,
35 *          Mark Wyse
36 */
37
38#include "gpu-compute/scoreboard_check_stage.hh"
39
40#include "gpu-compute/compute_unit.hh"
41#include "gpu-compute/gpu_static_inst.hh"
42#include "gpu-compute/shader.hh"
43#include "gpu-compute/wavefront.hh"
44#include "params/ComputeUnit.hh"
45
46ScoreboardCheckStage::ScoreboardCheckStage(const ComputeUnitParams *p)
47    : numSIMDs(p->num_SIMDs),
48      numMemUnits(p->num_global_mem_pipes + p->num_shared_mem_pipes),
49      numShrMemPipes(p->num_shared_mem_pipes),
50      vectorAluInstAvail(nullptr),
51      lastGlbMemSimd(-1),
52      lastShrMemSimd(-1), glbMemInstAvail(nullptr),
53      shrMemInstAvail(nullptr)
54{
55}
56
57ScoreboardCheckStage::~ScoreboardCheckStage()
58{
59    readyList.clear();
60    waveStatusList.clear();
61    shrMemInstAvail = nullptr;
62    glbMemInstAvail = nullptr;
63}
64
65void
66ScoreboardCheckStage::init(ComputeUnit *cu)
67{
68    computeUnit = cu;
69    _name = computeUnit->name() + ".ScoreboardCheckStage";
70
71    for (int unitId = 0; unitId < numSIMDs + numMemUnits; ++unitId) {
72        readyList.push_back(&computeUnit->readyList[unitId]);
73    }
74
75    for (int unitId = 0; unitId < numSIMDs; ++unitId) {
76        waveStatusList.push_back(&computeUnit->waveStatusList[unitId]);
77    }
78
79    vectorAluInstAvail = &computeUnit->vectorAluInstAvail;
80    glbMemInstAvail= &computeUnit->glbMemInstAvail;
81    shrMemInstAvail= &computeUnit->shrMemInstAvail;
82}
83
84void
85ScoreboardCheckStage::initStatistics()
86{
87    lastGlbMemSimd = -1;
88    lastShrMemSimd = -1;
89    *glbMemInstAvail = 0;
90    *shrMemInstAvail = 0;
91
92    for (int unitId = 0; unitId < numSIMDs; ++unitId)
93        vectorAluInstAvail->at(unitId) = false;
94}
95
96void
97ScoreboardCheckStage::collectStatistics(Wavefront *curWave, int unitId)
98{
99    if (curWave->instructionBuffer.empty())
100        return;
101
102    // track which vector SIMD unit has at least one WV with a vector
103    // ALU as the oldest instruction in its Instruction buffer
104    vectorAluInstAvail->at(unitId) = vectorAluInstAvail->at(unitId) ||
105                                     curWave->isOldestInstALU();
106
107    // track how many vector SIMD units have at least one WV with a
108    // vector Global memory instruction as the oldest instruction
109    // in its Instruction buffer
110    if ((curWave->isOldestInstGMem() || curWave->isOldestInstPrivMem() ||
111         curWave->isOldestInstFlatMem()) && lastGlbMemSimd != unitId &&
112        *glbMemInstAvail <= 1) {
113        (*glbMemInstAvail)++;
114        lastGlbMemSimd = unitId;
115    }
116
117    // track how many vector SIMD units have at least one WV with a
118    // vector shared memory (LDS) instruction as the oldest instruction
119    // in its Instruction buffer
120    // TODO: parametrize the limit of the LDS units
121    if (curWave->isOldestInstLMem() && (*shrMemInstAvail <= numShrMemPipes) &&
122        lastShrMemSimd != unitId) {
123        (*shrMemInstAvail)++;
124        lastShrMemSimd = unitId;
125    }
126}
127
128void
129ScoreboardCheckStage::exec()
130{
131    initStatistics();
132
133    // reset the ready list for all execution units; it will be
134    // constructed every cycle since resource availability may change
135    for (int unitId = 0; unitId < numSIMDs + numMemUnits; ++unitId) {
136        readyList[unitId]->clear();
137    }
138
139    // iterate over the Wavefronts of all SIMD units
140    for (int unitId = 0; unitId < numSIMDs; ++unitId) {
141        for (int wvId = 0; wvId < computeUnit->shader->n_wf; ++wvId) {
142            // reset the ready status of each wavefront
143            waveStatusList[unitId]->at(wvId).second = BLOCKED;
144            Wavefront *curWave = waveStatusList[unitId]->at(wvId).first;
145            collectStatistics(curWave, unitId);
146
147            if (curWave->ready(Wavefront::I_ALU)) {
148                readyList[unitId]->push_back(curWave);
149                waveStatusList[unitId]->at(wvId).second = READY;
150            } else if (curWave->ready(Wavefront::I_GLOBAL)) {
151                if (computeUnit->cedeSIMD(unitId, wvId)) {
152                    continue;
153                }
154
155                readyList[computeUnit->GlbMemUnitId()]->push_back(curWave);
156                waveStatusList[unitId]->at(wvId).second = READY;
157            } else if (curWave->ready(Wavefront::I_SHARED)) {
158                readyList[computeUnit->ShrMemUnitId()]->push_back(curWave);
159                waveStatusList[unitId]->at(wvId).second = READY;
160            } else if (curWave->ready(Wavefront::I_FLAT)) {
161                readyList[computeUnit->GlbMemUnitId()]->push_back(curWave);
162                waveStatusList[unitId]->at(wvId).second = READY;
163            } else if (curWave->ready(Wavefront::I_PRIVATE)) {
164                readyList[computeUnit->GlbMemUnitId()]->push_back(curWave);
165                waveStatusList[unitId]->at(wvId).second = READY;
166            }
167        }
168    }
169}
170
171void
172ScoreboardCheckStage::regStats()
173{
174}
175