gem5 v24.0.0.0
Loading...
Searching...
No Matches
dma_thread.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
33
34#include "debug/ProtocolTest.hh"
35
36namespace gem5
37{
38
40 : TesterThread(_params)
41{
42 threadName = "DmaThread(Thread ID " + std::to_string(threadId) + ")";
43 threadEvent.setDesc("DmaThread tick");
44 assert(numLanes == 1);
45}
46
51
52void
54{
55 assert(curAction);
57 // we should not have any outstanding fence or atomic op at this point
58 assert(pendingFenceCount == 0);
59 assert(pendingAtomicCount == 0);
60
61 // DMA thread is a scalar thread so always set lane to zero. This allows
62 // us to reuse the API for GPU threads rather than have a specific API
63 // for scalar tester threads
64 int lane = 0;
65
66 Location location = curAction->getLocation(lane);
67 assert(location >= AddressManager::INVALID_LOCATION);
68
69 if (location >= 0) {
70 Addr address = addrManager->getAddress(location);
71 DPRINTF(ProtocolTest, "%s Episode %d: Issuing Load - Addr %s\n",
73 ruby::printAddress(address));
74
75 int load_size = sizeof(Value);
76
77 // for now, assert address is 4-byte aligned
78 assert(address % load_size == 0);
79
80 auto req = std::make_shared<Request>(address, load_size,
81 0, tester->requestorId(),
82 0, threadId, nullptr);
83 req->setPaddr(address);
84 req->setReqInstSeqNum(tester->getActionSeqNum());
85
86 PacketPtr pkt = new Packet(req, MemCmd::ReadReq);
87 uint8_t* data = new uint8_t[load_size];
88 pkt->dataDynamic(data);
90
91 if (!port->sendTimingReq(pkt)) {
92 panic("Not expected failed sendTimingReq\n");
93 }
94
95 // insert an outstanding load
96 addOutstandingReqs(outstandingLoads, address, lane, location);
97
98 // increment the number of outstanding ld_st requests
100 }
101}
102
103void
105{
106 assert(curAction);
108 // we should not have any outstanding fence or atomic op at this point
109 assert(pendingFenceCount == 0);
110 assert(pendingAtomicCount == 0);
111
112 // DMA thread is a scalar thread so always set lane to zero. This allows
113 // us to reuse the API for GPU threads rather than have a specific API
114 // for scalar tester threads
115 int lane = 0;
116
117 Location location = curAction->getLocation(lane);
118 assert(location >= AddressManager::INVALID_LOCATION);
119
120 if (location >= 0) {
121 // prepare the next value to store
122 Value new_value = addrManager->getLoggedValue(location) + 1;
123
124 Addr address = addrManager->getAddress(location);
125 // must be aligned with store size
126 assert(address % sizeof(Value) == 0);
127
128 DPRINTF(ProtocolTest, "%s Episode %d: Issuing Store - Addr %s - "
129 "Value %d\n", this->getName(),
131 new_value);
132
133 auto req = std::make_shared<Request>(address, sizeof(Value),
134 0, tester->requestorId(), 0,
135 threadId, nullptr);
136 req->setPaddr(address);
137 req->setReqInstSeqNum(tester->getActionSeqNum());
138
139 PacketPtr pkt = new Packet(req, MemCmd::WriteReq);
140 uint8_t *writeData = new uint8_t[sizeof(Value)];
141 for (int j = 0; j < sizeof(Value); ++j) {
142 writeData[j] = ((uint8_t*)&new_value)[j];
143 }
144 pkt->dataDynamic(writeData);
146
147 if (!port->sendTimingReq(pkt)) {
148 panic("Not expecting a failed sendTimingReq\n");
149 }
150
151 // add an outstanding store
152 addOutstandingReqs(outstandingStores, address, lane, location,
153 new_value);
154
155 // increment the number of outstanding ld_st requests
157 }
158}
159
160void
162{
163 DPRINTF(ProtocolTest, "Issuing Atomic Op ...\n");
164
165 assert(curAction);
167 // we should not have any outstanding ops at this point
168 assert(pendingFenceCount == 0);
169 assert(pendingLdStCount == 0);
170 assert(pendingAtomicCount == 0);
171
172 // no-op: No DMA protocol exists with Atomics
173}
174
175void
177{
178 DPRINTF(ProtocolTest, "Issuing Acquire Op ...\n");
179
180 assert(curAction);
182 // we should not have any outstanding ops at this point
183 assert(pendingFenceCount == 0);
184 assert(pendingLdStCount == 0);
185 assert(pendingAtomicCount == 0);
186
187 // no-op: Acquire does not apply to DMA threads
188}
189
190void
192{
193 DPRINTF(ProtocolTest, "Issuing Release Op ...\n");
194
195 assert(curAction);
197 // we should not have any outstanding ops at this point
198 assert(pendingFenceCount == 0);
199 assert(pendingLdStCount == 0);
200 assert(pendingAtomicCount == 0);
201
202 // no-op: Release does not apply to DMA threads
203}
204
205void
207{
208 assert(pkt);
209 MemCmd resp_cmd = pkt->cmd;
210 Addr addr = pkt->getAddr();
211
212 DPRINTF(ProtocolTest, "%s Episode %d: hitCallback - Command %s -"
213 " Addr %s\n", this->getName(), curEpisode->getEpisodeId(),
214 resp_cmd.toString(), ruby::printAddress(addr));
215
216 if (resp_cmd == MemCmd::SwapResp) {
217 // response to a pending atomic
218 assert(pendingAtomicCount > 0);
219 assert(pendingLdStCount == 0);
220 assert(outstandingAtomics.count(addr) > 0);
221
222 // get return data
223 Value value = *(pkt->getPtr<Value>());
224
225 // validate atomic op return
227 assert(req.lane == 0);
228 validateAtomicResp(req.origLoc, req.lane, value);
229
230 // update log table
232 curEpisode->getEpisodeId(), value,
233 curTick(),
234 0);
235
236 // this Atomic is done
238 } else if (resp_cmd == MemCmd::ReadResp) {
239 // response to a pending read
240 assert(pendingLdStCount > 0);
241 assert(pendingAtomicCount == 0);
242 assert(outstandingLoads.count(addr) > 0);
243
244 // get return data
245 Value value = *(pkt->getPtr<Value>());
247 assert(req.lane == 0);
248 validateLoadResp(req.origLoc, req.lane, value);
249
250 // this Read is done
252 } else if (resp_cmd == MemCmd::WriteResp) {
253 // response to a pending write
254 assert(pendingLdStCount > 0);
255 assert(pendingAtomicCount == 0);
256
257 // no need to validate Write response
258 // just pop it from the outstanding req table so that subsequent
259 // requests dependent on this write can proceed
260 // note that unlike GpuWavefront we do decrement pendingLdStCount here
261 // since the write is guaranteed to be completed in downstream memory.
262 assert(outstandingStores.count(addr) > 0);
265
266 // update log table
269 req.storedValue,
270 curTick(),
271 0);
272
273 // the Write is now done
275 } else {
276 panic("UnsupportedMemCmd response type: %s",
277 resp_cmd.toString().c_str());
278 }
279
280 delete pkt->senderState;
281 delete pkt;
282
283 // record the last active cycle to check for deadlock
285
286 // we may be able to issue an action. Let's check
287 if (!threadEvent.scheduled()) {
289 }
290}
291
292} // namespace gem5
#define DPRINTF(x,...)
Definition trace.hh:210
const char data[]
Addr getAddress(Location loc)
Value getLoggedValue(Location loc) const
void updateLogTable(Location loc, int threadId, int episodeId, Value new_value, Tick curTick, int cuId=-1)
static const int INVALID_LOCATION
static const int INVALID_VALUE
Cycles curCycle() const
Determine the current cycle, corresponding to a tick aligned to a clock edge.
void issueAtomicOps()
void issueReleaseOp()
DmaThreadParams Params
Definition dma_thread.hh:44
void issueAcquireOp()
void issueLoadOps()
Definition dma_thread.cc:53
virtual ~DmaThread()
Definition dma_thread.cc:47
DmaThread(const Params &_params)
Definition dma_thread.cc:39
AddressManager::Location Location
Definition dma_thread.hh:48
AddressManager::Value Value
Definition dma_thread.hh:49
void hitCallback(PacketPtr pkt)
Location getLocation(int lane) const
Definition episode.cc:290
Type getType() const
Definition episode.hh:66
int getEpisodeId() const
Definition episode.hh:85
const std::string & toString() const
Return the string to a cmd given by idx.
Definition packet.hh:276
A Packet is used to encapsulate a transfer between two objects in the memory system (e....
Definition packet.hh:295
Addr getAddr() const
Definition packet.hh:807
SenderState * senderState
This packet's sender state.
Definition packet.hh:545
T * getPtr()
get a pointer to the data ptr.
Definition packet.hh:1225
void dataDynamic(T *p)
Set the data pointer to a value that should have delete [] called on it.
Definition packet.hh:1213
MemCmd cmd
The command field of the packet.
Definition packet.hh:372
bool sendTimingReq(PacketPtr pkt)
Attempt to send a timing request to the responder port by calling its corresponding receive function.
Definition port.hh:603
void setDesc(std::string _description)
AddressManager * addrManager
OutstandingReqTable outstandingAtomics
void validateAtomicResp(Location loc, int lane, Value ret_val)
ProtocolTester * tester
ProtocolTester::SeqPort * port
OutstandingReqTable outstandingStores
void addOutstandingReqs(OutstandingReqTable &req_table, Addr addr, int lane, Location loc, Value stored_val=AddressManager::INVALID_VALUE)
OutstandingReqTable outstandingLoads
OutstandingReq popOutstandingReq(OutstandingReqTable &req_table, Addr address)
const Episode::Action * curAction
TesterThreadEvent threadEvent
const std::string & getName() const
void validateLoadResp(Location loc, int lane, Value ret_val)
bool scheduled() const
Determine if the current event is scheduled.
Definition eventq.hh:458
#define panic(...)
This implements a cprintf based panic() function.
Definition logging.hh:188
Bitfield< 3 > addr
Definition types.hh:84
std::string printAddress(Addr addr)
Definition Address.cc:80
Copyright (c) 2024 - Pranith Kumar Copyright (c) 2020 Inria All rights reserved.
Definition binary32.hh:36
Tick curTick()
The universal simulation clock.
Definition cur_tick.hh:46
uint64_t Addr
Address type This will probably be moved somewhere else in the near future.
Definition types.hh:147

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