gem5  [DEVELOP-FOR-23.0]
All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Modules Pages
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 
38 namespace gem5
39 {
40 
41 // return the min number of elements that the manager can reserve given
42 // a request for "size" elements
43 uint32_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 
53 std::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
81 void
82 DynPoolManager::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 
92 bool
93 DynPoolManager::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 
116 uint32_t
117 DynPoolManager::allocateRegion(const uint32_t size,
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 
152 void
153 DynPoolManager::freeRegion(uint32_t firstIdx,
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 
193 uint32_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
gem5::DynPoolManager::regionSize
uint32_t regionSize(std::pair< uint32_t, uint32_t > &region) override
Definition: dyn_pool_manager.cc:194
gem5::DynPoolManager::freeSpaceRecord
std::list< std::pair< int, int > > freeSpaceRecord
Definition: dyn_pool_manager.hh:70
gem5::DynPoolManager::totalRegSpace
int totalRegSpace
Definition: dyn_pool_manager.hh:73
sc_dt::to_string
const std::string to_string(sc_enc enc)
Definition: sc_fxdefs.cc:91
gem5::DynPoolManager::canAllocate
bool canAllocate(uint32_t numRegions, uint32_t size) override
Definition: dyn_pool_manager.cc:93
dyn_pool_manager.hh
gem5::DynPoolManager::minAllocatedElements
uint32_t minAllocatedElements(uint32_t size)
Definition: dyn_pool_manager.cc:44
gem5::DynPoolManager::resetRegion
void resetRegion(const int &regsPerSimd) override
Definition: dyn_pool_manager.cc:82
DPRINTF
#define DPRINTF(x,...)
Definition: trace.hh:210
gem5::PoolManager::minAllocation
uint32_t minAllocation()
Definition: pool_manager.hh:51
gem5::DynPoolManager::_regionSize
uint32_t _regionSize
Definition: dyn_pool_manager.hh:66
gem5::DynPoolManager::allocateRegion
uint32_t allocateRegion(const uint32_t size, uint32_t *reservedPoolSize) override
Definition: dyn_pool_manager.cc:117
gem5::DynPoolManager::_totRegSpaceAvailable
uint32_t _totRegSpaceAvailable
Definition: dyn_pool_manager.hh:68
std::pair< int, int >
gem5::DynPoolManager::printRegion
std::string printRegion() override
Definition: dyn_pool_manager.cc:54
logging.hh
gem5::DynPoolManager::reservedSpaceRecord
int reservedSpaceRecord
Definition: dyn_pool_manager.hh:71
trace.hh
gem5::DynPoolManager::freeRegion
void freeRegion(uint32_t firstIdx, uint32_t lastIdx) override
Definition: dyn_pool_manager.cc:153
gem5::PoolManager::poolSize
uint32_t poolSize()
Definition: pool_manager.hh:60
fatal_if
#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
gem5
Reference material can be found at the JEDEC website: UFS standard http://www.jedec....
Definition: gpu_translation_state.hh:37

Generated on Sun Jul 30 2023 01:56:57 for gem5 by doxygen 1.8.17