gem5  v22.1.0.0
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 
36 namespace 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 
48 {
49 
50 }
51 
52 void
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",
72  this->getName(), curEpisode->getEpisodeId(),
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 
103 void
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);
145  pkt->senderState = new ProtocolTester::SenderState(this);
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 
160 void
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 
175 void
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 
190 void
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 
205 void
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()) {
288  scheduleWakeup();
289  }
290 }
291 
292 } // namespace gem5
#define DPRINTF(x,...)
Definition: trace.hh:186
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()
Definition: dma_thread.cc:161
void issueReleaseOp()
Definition: dma_thread.cc:191
DmaThreadParams Params
Definition: dma_thread.hh:44
void issueAcquireOp()
Definition: dma_thread.cc:176
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 issueStoreOps()
Definition: dma_thread.cc:104
void hitCallback(PacketPtr pkt)
Definition: dma_thread.cc:206
Location getLocation(int lane) const
Definition: episode.cc:289
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:275
A Packet is used to encapsulate a transfer between two objects in the memory system (e....
Definition: packet.hh:294
T * getPtr()
get a pointer to the data ptr.
Definition: packet.hh:1212
Addr getAddr() const
Definition: packet.hh:805
SenderState * senderState
This packet's sender state.
Definition: packet.hh:544
void dataDynamic(T *p)
Set the data pointer to a value that should have delete [] called on it.
Definition: packet.hh:1200
MemCmd cmd
The command field of the packet.
Definition: packet.hh:371
RequestorID requestorId()
bool sendTimingReq(PacketPtr pkt)
Attempt to send a timing request to the responder port by calling its corresponding receive function.
Definition: port.hh:495
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
std::string threadName
void addOutstandingReqs(OutstandingReqTable &req_table, Addr addr, int lane, Location loc, Value stored_val=AddressManager::INVALID_VALUE)
const std::string & getName() const
OutstandingReqTable outstandingLoads
OutstandingReq popOutstandingReq(OutstandingReqTable &req_table, Addr address)
const Episode::Action * curAction
TesterThreadEvent threadEvent
void validateLoadResp(Location loc, int lane, Value ret_val)
bool scheduled() const
Determine if the current event is scheduled.
Definition: eventq.hh:465
#define panic(...)
This implements a cprintf based panic() function.
Definition: logging.hh:178
Bitfield< 24 > j
Definition: misc_types.hh:57
Bitfield< 3 > addr
Definition: types.hh:84
ProbePointArg< PacketInfo > Packet
Packet probe point.
Definition: mem.hh:109
std::string printAddress(Addr addr)
Definition: Address.cc:80
Reference material can be found at the JEDEC website: UFS standard http://www.jedec....
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
RubyTester::SenderState SenderState
Definition: Check.cc:40
const std::string to_string(sc_enc enc)
Definition: sc_fxdefs.cc:60

Generated on Wed Dec 21 2022 10:22:31 for gem5 by doxygen 1.9.1