gem5 v24.0.0.0
Loading...
Searching...
No Matches
dyn_pool_manager.cc
Go to the documentation of this file.
1/*
2 * Copyright (c) 2020 Advanced Micro Devices, Inc.
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions are met:
7 *
8 * 1. Redistributions of source code must retain the above copyright notice,
9 * this list of conditions and the following disclaimer.
10 *
11 * 2. Redistributions in binary form must reproduce the above copyright notice,
12 * this list of conditions and the following disclaimer in the documentation
13 * and/or other materials provided with the distribution.
14 *
15 * 3. Neither the name of the copyright holder nor the names of its
16 * contributors may be used to endorse or promote products derived from this
17 * software without specific prior written permission.
18 *
19 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
20 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
23 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
24 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
25 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
26 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
27 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
28 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
29 * POSSIBILITY OF SUCH DAMAGE.
30 *
31 */
32
33#include "base/logging.hh"
34#include "base/trace.hh"
35#include "debug/GPUVRF.hh"
37
38namespace gem5
39{
40
41// return the min number of elements that the manager can reserve given
42// a request for "size" elements
43uint32_t
45{
46 fatal_if(size <= 0 || size > poolSize(), "Illegal VGPR region size=%d\n",
47 size);
48
49 return size % minAllocation() > 0 ?
50 (minAllocation() - (size % minAllocation())) + size : size;
51}
52
53std::string
55{
56 std::string _cout;
57 uint32_t reservedEntries = 0;
58
59 /*
60 Iterate over all elements in freeSpaceRecord, checking first element
61 of each pair to see how much space in it has been allocated already.
62 This only counts the partially allocated regions. Thus, in addition,
63 count the elements in reservedSpaceRecord.
64 */
65 auto it_free = freeSpaceRecord.begin();
66 while (it_free != freeSpaceRecord.end()) {
67 reservedEntries += it_free->first;
68 ++it_free;
69 }
70 reservedEntries += (reservedSpaceRecord * totalRegSpace);
71
72 if (reservedEntries == 0)
73 _cout = "VRF is empty\n";
74 else {
75 _cout = "VRF reserves " + std::to_string(reservedEntries) + " VGPRs\n";
76 }
77 return _cout;
78}
79
80// reset freeSpace and reservedSpace
81void
82DynPoolManager::resetRegion(const int & regsPerSimd){
83 totalRegSpace = regsPerSimd;
85 freeSpaceRecord.clear();
86
87 // reset available free space
88 _totRegSpaceAvailable = regsPerSimd;
89 freeSpaceRecord.push_back(std::make_pair(0,regsPerSimd));
90}
91
92bool
93DynPoolManager::canAllocate(uint32_t numRegions, uint32_t size)
94{
95 uint32_t actualSize = minAllocatedElements(size);
96 uint32_t numAvailChunks = 0;
97 DPRINTF(GPUVRF, "Checking if we can allocate %d regions of size %d "
98 "registers\n", numRegions, actualSize);
99 for (auto it : freeSpaceRecord) {
100 numAvailChunks += (it.second - it.first)/actualSize;
101 }
102
103 if (numAvailChunks >= numRegions) {
104 DPRINTF(GPUVRF, "Able to allocate %d regions of size %d; "
105 "number of available regions: %d\n",
106 numRegions, actualSize, numAvailChunks);
107 return true;
108 } else {
109 DPRINTF(GPUVRF, "Unable to allocate %d regions of size %d; "
110 "number of available regions: %d\n",
111 numRegions, actualSize, numAvailChunks);
112 return false;
113 }
114}
115
116uint32_t
118 uint32_t *reservedPoolSize)
119{
120 uint32_t startIdx = (unsigned)-1;
121 uint32_t actualSize = minAllocatedElements(size);
122 auto it = freeSpaceRecord.begin();
123 while (it != freeSpaceRecord.end()) {
124 uint32_t curChunkSize = it->second - it->first;
125 if (curChunkSize >= actualSize) {
126 // assign the next block starting from here
127 startIdx = it->first;
128 _regionSize = actualSize;
129 *reservedPoolSize = actualSize;
130 _totRegSpaceAvailable -= actualSize;
131
132 // This case sees if this chunk size is exactly equal to
133 // the size of the requested chunk. If yes, then this can't
134 // contribute to future requests and hence, should be removed
135 if (curChunkSize == actualSize) {
136 it = freeSpaceRecord.erase(it);
137 // once entire freeSpaceRecord allocated, increment
138 // reservedSpaceRecord count
140 } else {
141 it->first += actualSize;
142 }
143 break;
144 }
145 it++;
146 }
147 DPRINTF(GPUVRF,"totRegSpace %d allocating Register at %d and"
148 " size %d\n",_totRegSpaceAvailable,startIdx,actualSize);
149 return startIdx;
150}
151
152void
154 uint32_t lastIdx)
155{
156 // lastIdx-firstIdx should give the size of free space
157 DPRINTF(GPUVRF,"freeing Region at %d %d, size %d\n",
158 firstIdx,lastIdx,lastIdx-firstIdx);
159
160 // Current dynamic register allocation does not handle wraparound
161 assert(firstIdx < lastIdx);
162 _totRegSpaceAvailable += lastIdx-firstIdx;
163
164 // Consolidate with other regions. Need to check if firstIdx or lastIdx
165 // already exist
166 auto firstIt = std::find_if(
167 freeSpaceRecord.begin(),
168 freeSpaceRecord.end(),
169 [&](const std::pair<int, int>& element){
170 return element.second == firstIdx;} );
171
172 auto lastIt = std::find_if(
173 freeSpaceRecord.begin(),
174 freeSpaceRecord.end(),
175 [&](const std::pair<int, int>& element){
176 return element.first == lastIdx;} );
177
178 if (firstIt != freeSpaceRecord.end() && lastIt != freeSpaceRecord.end()) {
179 firstIt->second = lastIt->second;
180 freeSpaceRecord.erase(lastIt);
181 } else if (firstIt != freeSpaceRecord.end()) {
182 firstIt->second = lastIdx;
183 } else if (lastIt != freeSpaceRecord.end()) {
184 lastIt->first = firstIdx;
185 } else {
186 freeSpaceRecord.push_back(std::make_pair(firstIdx, lastIdx));
187 }
188
189 // remove corresponding entry from reservedSpaceRecord too
191}
192
193uint32_t
195{
196 bool wrapAround = (region.first > region.second);
197 if (!wrapAround) {
198 return region.second - region.first + 1;
199 } else {
200 return region.second + poolSize() - region.first + 1;
201 }
202}
203
204} // namespace gem5
#define DPRINTF(x,...)
Definition trace.hh:210
void resetRegion(const int &regsPerSimd) override
std::string printRegion() override
std::list< std::pair< int, int > > freeSpaceRecord
uint32_t allocateRegion(const uint32_t size, uint32_t *reservedPoolSize) override
uint32_t minAllocatedElements(uint32_t size)
uint32_t regionSize(std::pair< uint32_t, uint32_t > &region) override
void freeRegion(uint32_t firstIdx, uint32_t lastIdx) override
bool canAllocate(uint32_t numRegions, uint32_t size) override
uint32_t poolSize()
uint32_t minAllocation()
STL pair class.
Definition stl.hh:58
#define fatal_if(cond,...)
Conditional fatal macro that checks the supplied condition and only causes a fatal error if the condi...
Definition logging.hh:236
Copyright (c) 2024 - Pranith Kumar Copyright (c) 2020 Inria All rights reserved.
Definition binary32.hh:36

Generated on Tue Jun 18 2024 16:24:04 for gem5 by doxygen 1.11.0