2 * Copyright (c) 2014-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
18 * contributors may be used to endorse or promote products derived from this
19 * software 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.
34 #include "gpu-compute/schedule_stage.hh"
36 #include "gpu-compute/compute_unit.hh"
37 #include "gpu-compute/gpu_static_inst.hh"
38 #include "gpu-compute/vector_register_file.hh"
39 #include "gpu-compute/wavefront.hh"
41 ScheduleStage::ScheduleStage(const ComputeUnitParams
*p
)
42 : numSIMDs(p
->num_SIMDs
),
43 numMemUnits(p
->num_global_mem_pipes
+ p
->num_shared_mem_pipes
)
45 for (int j
= 0; j
< numSIMDs
+ numMemUnits
; ++j
) {
46 scheduler
.emplace_back(p
);
50 ScheduleStage::~ScheduleStage()
53 waveStatusList
.clear();
57 ScheduleStage::init(ComputeUnit
*cu
)
60 _name
= computeUnit
->name() + ".ScheduleStage";
62 for (int j
= 0; j
< numSIMDs
+ numMemUnits
; ++j
) {
63 scheduler
[j
].bindList(&computeUnit
->readyList
[j
]);
66 for (int j
= 0; j
< numSIMDs
; ++j
) {
67 waveStatusList
.push_back(&computeUnit
->waveStatusList
[j
]);
70 dispatchList
= &computeUnit
->dispatchList
;
74 ScheduleStage::arbitrate()
76 // iterate over all Memory pipelines
77 for (int j
= numSIMDs
; j
< numSIMDs
+ numMemUnits
; ++j
) {
78 if (dispatchList
->at(j
).first
) {
79 Wavefront
*waveToMemPipe
= dispatchList
->at(j
).first
;
80 // iterate over all execution pipelines
81 for (int i
= 0; i
< numSIMDs
+ numMemUnits
; ++i
) {
82 if ((i
!= j
) && (dispatchList
->at(i
).first
)) {
83 Wavefront
*waveToExePipe
= dispatchList
->at(i
).first
;
84 // if the two selected wavefronts are mapped to the same
85 // SIMD unit then they share the VRF
86 if (waveToMemPipe
->simdId
== waveToExePipe
->simdId
) {
87 int simdId
= waveToMemPipe
->simdId
;
88 // Read VRF port arbitration:
89 // If there are read VRF port conflicts between the
90 // a memory and another instruction we drop the other
91 // instruction. We don't need to check for write VRF
92 // port conflicts because the memory instruction either
93 // does not need to write to the VRF (store) or will
94 // write to the VRF when the data comes back (load) in
95 // which case the arbiter of the memory pipes will
96 // resolve any conflicts
97 if (computeUnit
->vrf
[simdId
]->
98 isReadConflict(waveToMemPipe
->wfSlotId
,
99 waveToExePipe
->wfSlotId
)) {
100 // FIXME: The "second" member variable is never
101 // used in the model. I am setting it to READY
102 // simply to follow the protocol of setting it
103 // when the WF has an instruction ready to issue
104 waveStatusList
[simdId
]->at(waveToExePipe
->wfSlotId
)
107 dispatchList
->at(i
).first
= nullptr;
108 dispatchList
->at(i
).second
= EMPTY
;
119 ScheduleStage::exec()
121 for (int j
= 0; j
< numSIMDs
+ numMemUnits
; ++j
) {
122 uint32_t readyListSize
= computeUnit
->readyList
[j
].size();
124 // If no wave is ready to be scheduled on the execution resource
125 // then skip scheduling for this execution resource
126 if (!readyListSize
) {
130 Wavefront
*waveToBeDispatched
= scheduler
[j
].chooseWave();
131 dispatchList
->at(j
).first
= waveToBeDispatched
;
132 waveToBeDispatched
->updateResources();
133 dispatchList
->at(j
).second
= FILLED
;
135 waveStatusList
[waveToBeDispatched
->simdId
]->at(
136 waveToBeDispatched
->wfSlotId
).second
= BLOCKED
;
138 assert(computeUnit
->readyList
[j
].size() == readyListSize
- 1);
140 // arbitrate over all shared resources among instructions being issued
146 ScheduleStage::regStats()