gem5  [DEVELOP-FOR-23.0]
All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Modules Pages
memory_manager.cc
Go to the documentation of this file.
1 /*
2  * Copyright (c) 2021 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 
34 
35 #include <memory>
36 
37 #include "base/chunk_generator.hh"
38 #include "debug/AMDGPUMem.hh"
39 #include "params/AMDGPUMemoryManager.hh"
40 #include "sim/system.hh"
41 
42 namespace gem5
43 {
44 
45 AMDGPUMemoryManager::AMDGPUMemoryManager(const AMDGPUMemoryManagerParams &p)
46  : ClockedObject(p), _gpuMemPort(csprintf("%s-port", name()), *this),
47  cacheLineSize(p.system->cacheLineSize()),
48  _requestorId(p.system->getRequestorId(this))
49 {
50 }
51 
52 void
54  Request::Flags flag, Event *callback)
55 {
56  assert(data);
57 
58  // Requests may return out of order, so we should track how many chunks
59  // are outstanding and if the last chunk was sent. Give each status struct
60  // a unique ID so that DMAs to the same address may occur at the same time
61  requestStatus.emplace(std::piecewise_construct,
62  std::forward_as_tuple(requestId), std::tuple<>{});
63 
64  DPRINTF(AMDGPUMem, "Created status for write request %ld\n", requestId);
65 
66  ChunkGenerator gen(addr, size, cacheLineSize);
67  for (; !gen.done(); gen.next()) {
68  RequestPtr req = std::make_shared<Request>(gen.addr(), gen.size(),
69  flag, _requestorId);
70 
71  PacketPtr pkt = Packet::createWrite(req);
72  uint8_t *dataPtr = new uint8_t[gen.size()];
73  std::memcpy(dataPtr, data + (gen.complete()/sizeof(uint8_t)),
74  gen.size());
75  pkt->dataDynamic<uint8_t>(dataPtr);
76 
77  pkt->pushSenderState(
78  new GPUMemPort::SenderState(callback, addr, requestId));
79  requestStatus.at(requestId).outstandingChunks++;
80  if (gen.last()) {
81  requestStatus.at(requestId).sentLastChunk = true;
82  }
83 
84  if (!_gpuMemPort.sendTimingReq(pkt)) {
85  DPRINTF(AMDGPUMem, "Request to %#lx needs retry\n", gen.addr());
86  _gpuMemPort.retries.push_back(pkt);
87  } else {
88  DPRINTF(AMDGPUMem, "Write request to %#lx sent\n", gen.addr());
89  }
90  }
91 
92  requestId++;
93 }
94 
95 void
97  Request::Flags flag, Event *callback)
98 {
99  assert(data);
100  uint8_t *dataPtr = data;
101 
102  // Requests may return out of order, so we should track how many chunks
103  // are outstanding and if the last chunk was sent. Give each status struct
104  // a unique ID so that DMAs to the same address may occur at the same time
105  requestStatus.emplace(std::piecewise_construct,
106  std::forward_as_tuple(requestId), std::tuple<>{});
107 
108  DPRINTF(AMDGPUMem, "Created status for read request %ld\n", requestId);
109 
110  ChunkGenerator gen(addr, size, cacheLineSize);
111  for (; !gen.done(); gen.next()) {
112  RequestPtr req = std::make_shared<Request>(gen.addr(), gen.size(),
113  flag, _requestorId);
114 
115  PacketPtr pkt = Packet::createRead(req);
116  pkt->dataStatic<uint8_t>(dataPtr);
117  dataPtr += gen.size();
118 
119  pkt->pushSenderState(
120  new GPUMemPort::SenderState(callback, addr, requestId));
121  requestStatus.at(requestId).outstandingChunks++;
122  if (gen.last()) {
123  requestStatus.at(requestId).sentLastChunk = true;
124  }
125 
126  if (!_gpuMemPort.sendTimingReq(pkt)) {
127  DPRINTF(AMDGPUMem, "Request to %#lx needs retry\n", gen.addr());
128  _gpuMemPort.retries.push_back(pkt);
129  } else {
130  DPRINTF(AMDGPUMem, "Read request to %#lx sent\n", gen.addr());
131  }
132  }
133 
134  requestId++;
135 }
136 
137 bool
139 {
140  // Retrieve sender state
141  [[maybe_unused]] SenderState *sender_state =
142  safe_cast<SenderState*>(pkt->senderState);
143 
144  // Check if all chunks have completed, the last chunk was sent, and there
145  // is a callback, call the callback now.
146  assert(gpu_mem.requestStatus.count(sender_state->_requestId));
147  auto& status = gpu_mem.requestStatus.at(sender_state->_requestId);
148 
149  assert(status.outstandingChunks != 0);
150  status.outstandingChunks--;
151  DPRINTF(AMDGPUMem, "Received Response for %#x. %d chunks remain, sent "
152  "last = %d, requestId = %ld\n", sender_state->_addr,
153  status.outstandingChunks, status.sentLastChunk,
154  sender_state->_requestId);
155 
156  if (!status.outstandingChunks && status.sentLastChunk) {
157  // Call and free the callback if there is one
158  if (sender_state->_callback) {
159  DPRINTF(AMDGPUMem, "Calling callback for request %ld\n",
160  sender_state->_requestId);
161  sender_state->_callback->process();
162  delete sender_state->_callback;
163  }
164  DPRINTF(AMDGPUMem, "Deleting status for request %ld\n",
165  sender_state->_requestId);
166  gpu_mem.requestStatus.erase(sender_state->_requestId);
167  }
168 
169  delete pkt->senderState;
170  delete pkt;
171  return true;
172 }
173 
174 void
176 {
177  for (const auto &pkt : retries) {
178  if (!sendTimingReq(pkt)) {
179  break;
180  } else {
181  DPRINTF(AMDGPUMem, "Retry for %#lx sent\n", pkt->getAddr());
182  retries.pop_front();
183  }
184  }
185 }
186 
187 } // namespace gem5
gem5::AMDGPUMemoryManager::GPUMemPort::SenderState::_addr
Addr _addr
Definition: memory_manager.hh:66
gem5::AMDGPUMemoryManager::GPUMemPort::SenderState::_callback
Event * _callback
Definition: memory_manager.hh:65
gem5::AMDGPUMemoryManager::GPUMemPort::SenderState::_requestId
uint64_t _requestId
Definition: memory_manager.hh:67
gem5::RequestPort::sendTimingReq
bool sendTimingReq(PacketPtr pkt)
Attempt to send a timing request to the responder port by calling its corresponding receive function.
Definition: port.hh:587
system.hh
data
const char data[]
Definition: circlebuf.test.cc:48
gem5::ChunkGenerator::next
bool next()
Advance generator to next chunk.
Definition: chunk_generator.hh:185
gem5::ChunkGenerator::complete
Addr complete() const
Number of bytes we have already chunked up.
Definition: chunk_generator.hh:132
gem5::Packet::pushSenderState
void pushSenderState(SenderState *sender_state)
Push a new sender state to the packet and make the current sender state the predecessor of the new on...
Definition: packet.cc:334
gem5::AMDGPUMemoryManager::readRequest
void readRequest(Addr addr, uint8_t *data, int size, Request::Flags flag, Event *callback)
Read size amount of data from device memory at addr using flags and callback.
Definition: memory_manager.cc:96
gem5::AMDGPUMemoryManager::writeRequest
void writeRequest(Addr addr, uint8_t *data, int size, Request::Flags flag, Event *callback)
Write size amount of data to device memory at addr using flags and callback.
Definition: memory_manager.cc:53
gem5::Packet::createWrite
static PacketPtr createWrite(const RequestPtr &req)
Definition: packet.hh:1044
gem5::X86ISA::system
Bitfield< 15 > system
Definition: misc.hh:1004
gem5::AMDGPUMemoryManager::AMDGPUMemoryManager
AMDGPUMemoryManager(const AMDGPUMemoryManagerParams &p)
Definition: memory_manager.cc:45
gem5::AMDGPUMemoryManager::GPUMemPort::recvReqRetry
void recvReqRetry() override
Called by the peer if sendTimingReq was called on this peer (causing recvTimingReq to be called on th...
Definition: memory_manager.cc:175
gem5::csprintf
std::string csprintf(const char *format, const Args &...args)
Definition: cprintf.hh:161
gem5::ChunkGenerator::last
bool last() const
Is this the last chunk?
Definition: chunk_generator.hh:149
gem5::ChunkGenerator::size
Addr size() const
Return size in bytes of current chunk.
Definition: chunk_generator.hh:125
gem5::ChunkGenerator
This class takes an arbitrary memory region (address/length pair) and generates a series of appropria...
Definition: chunk_generator.hh:59
gem5::AMDGPUMemoryManager::GPUMemPort::recvTimingResp
bool recvTimingResp(PacketPtr pkt) override
Receive a timing response from the peer.
Definition: memory_manager.cc:138
gem5::Packet::dataStatic
void dataStatic(T *p)
Set the data pointer to the following value that should not be freed.
Definition: packet.hh:1175
memory_manager.hh
gem5::Flags< FlagsType >
gem5::ChunkGenerator::done
bool done() const
Are we done? That is, did the last call to next() advance past the end of the region?
Definition: chunk_generator.hh:141
gem5::VegaISA::p
Bitfield< 54 > p
Definition: pagetable.hh:70
gem5::AMDGPUMemoryManager::requestId
uint64_t requestId
Definition: memory_manager.hh:87
gem5::AMDGPUMemoryManager::_requestorId
const RequestorID _requestorId
Definition: memory_manager.hh:76
DPRINTF
#define DPRINTF(x,...)
Definition: trace.hh:210
gem5::Event
Definition: eventq.hh:254
gem5::Packet
A Packet is used to encapsulate a transfer between two objects in the memory system (e....
Definition: packet.hh:294
gem5::AMDGPUMemoryManager::GPUMemPort::retries
std::deque< PacketPtr > retries
Definition: memory_manager.hh:70
gem5::AMDGPUMemoryManager::GPUMemPort::gpu_mem
AMDGPUMemoryManager & gpu_mem
Definition: memory_manager.hh:71
gem5::Event::process
virtual void process()=0
gem5::RequestPtr
std::shared_ptr< Request > RequestPtr
Definition: request.hh:92
gem5::Addr
uint64_t Addr
Address type This will probably be moved somewhere else in the near future.
Definition: types.hh:147
gem5::Packet::senderState
SenderState * senderState
This packet's sender state.
Definition: packet.hh:545
name
const std::string & name()
Definition: trace.cc:48
gem5::ClockedObject
The ClockedObject class extends the SimObject with a clock and accessor functions to relate ticks to ...
Definition: clocked_object.hh:234
gem5::AMDGPUMemoryManager::_gpuMemPort
GPUMemPort _gpuMemPort
Definition: memory_manager.hh:74
gem5::AMDGPUMemoryManager::requestStatus
std::unordered_map< uint64_t, RequestStatus > requestStatus
Definition: memory_manager.hh:88
gem5::ChunkGenerator::addr
Addr addr() const
Return starting address of current chunk.
Definition: chunk_generator.hh:119
gem5::Packet::dataDynamic
void dataDynamic(T *p)
Set the data pointer to a value that should have delete [] called on it.
Definition: packet.hh:1213
chunk_generator.hh
gem5
Reference material can be found at the JEDEC website: UFS standard http://www.jedec....
Definition: gpu_translation_state.hh:37
gem5::Packet::createRead
static PacketPtr createRead(const RequestPtr &req)
Constructor-like methods that return Packets based on Request objects.
Definition: packet.hh:1038
gem5::AMDGPUMemoryManager::cacheLineSize
const int cacheLineSize
Definition: memory_manager.hh:75
gem5::AMDGPUMemoryManager::GPUMemPort::SenderState
Definition: memory_manager.hh:59
gem5::ArmISA::status
Bitfield< 5, 0 > status
Definition: misc_types.hh:480
gem5::X86ISA::addr
Bitfield< 3 > addr
Definition: types.hh:84

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