gem5  v21.1.0.2
gpu_wavefront.cc
Go to the documentation of this file.
1 /*
2  * Copyright (c) 2017-2021 Advanced Micro Devices, Inc.
3  * All rights reserved.
4  *
5  * For use for simulation and test purposes only
6  *
7  * Redistribution and use in source and binary forms, with or without
8  * modification, are permitted provided that the following conditions are met:
9  *
10  * 1. Redistributions of source code must retain the above copyright notice,
11  * this list of conditions and the following disclaimer.
12  *
13  * 2. Redistributions in binary form must reproduce the above copyright notice,
14  * this list of conditions and the following disclaimer in the documentation
15  * and/or other materials provided with the distribution.
16  *
17  * 3. Neither the name of the copyright holder nor the names of its
18  * contributors may be used to endorse or promote products derived from this
19  * software without specific prior written permission.
20  *
21  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
22  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
23  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
24  * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
25  * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
26  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
27  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
28  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
29  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
30  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
31  * POSSIBILITY OF SUCH DAMAGE.
32  */
33 
35 
36 #include "debug/ProtocolTest.hh"
37 
38 namespace gem5
39 {
40 
42  : TesterThread(p), cuId(p.cu_id)
43 {
44  threadName = "GpuWavefront(TesterThread ID = " + std::to_string(threadId) +
45  ", CU ID = " + std::to_string(cuId) + ")";
46  threadEvent.setDesc("GpuWavefront tick");
47 }
48 
50 {
51 
52 }
53 
54 void
56 {
57  assert(curAction);
59  // we should not have any outstanding fence or atomic op at this point
60  assert(pendingFenceCount == 0);
61  assert(pendingAtomicCount == 0);
62 
63  for (int lane = 0; lane < numLanes; ++lane) {
64  Location location = curAction->getLocation(lane);
65  assert(location >= AddressManager::INVALID_LOCATION);
66 
67  // Make a request if we do not get an INVALID_LOCATION for this lane.
68  if (location >= 0) {
69  Addr address = addrManager->getAddress(location);
70  DPRINTF(ProtocolTest, "%s Episode %d: Issuing Load - Addr %s\n",
71  this->getName(), curEpisode->getEpisodeId(),
72  ruby::printAddress(address));
73 
74  int load_size = sizeof(Value);
75 
76  // for now, assert address is 4-byte aligned
77  assert(address % load_size == 0);
78 
79  auto req = std::make_shared<Request>(address, load_size,
80  0, tester->requestorId(),
81  0, threadId, nullptr);
82  req->setPaddr(address);
83  req->setReqInstSeqNum(tester->getActionSeqNum());
84  // set protocol-specific flags
86 
87  PacketPtr pkt = new Packet(req, MemCmd::ReadReq);
88  uint8_t* data = new uint8_t[load_size];
89  pkt->dataDynamic(data);
91 
92  // increment the number of outstanding ld_st requests
94 
95  if (!port->sendTimingReq(pkt)) {
96  panic("Not expected failed sendTimingReq\n");
97  }
98 
99  // insert an outstanding load
100  addOutstandingReqs(outstandingLoads, address, lane, location);
101  }
102  }
103 }
104 
105 void
107 {
108  assert(curAction);
110  // we should not have any outstanding fence or atomic op at this point
111  assert(pendingFenceCount == 0);
112  assert(pendingAtomicCount == 0);
113 
114  for (int lane = 0; lane < numLanes; ++lane) {
115  Location location = curAction->getLocation(lane);
116  assert(location >= AddressManager::INVALID_LOCATION);
117 
118  // Make a request if we do not get an INVALID_LOCATION for this lane.
119  if (location >= 0) {
120  // prepare the next value to store
121  Value new_value = addrManager->getLoggedValue(location) + 1;
122 
123  Addr address = addrManager->getAddress(location);
124  // must be aligned with store size
125  assert(address % sizeof(Value) == 0);
126 
127  DPRINTF(ProtocolTest, "%s Episode %d: Issuing Store - Addr %s - "
128  "Value %d\n", this->getName(),
130  new_value);
131 
132  auto req = std::make_shared<Request>(address, sizeof(Value),
133  0, tester->requestorId(), 0,
134  threadId, nullptr);
135  req->setPaddr(address);
136  req->setReqInstSeqNum(tester->getActionSeqNum());
137  // set protocol-specific flags
139 
140  PacketPtr pkt = new Packet(req, MemCmd::WriteReq);
141  uint8_t *writeData = new uint8_t[sizeof(Value)];
142  for (int j = 0; j < sizeof(Value); ++j) {
143  writeData[j] = ((uint8_t*)&new_value)[j];
144  }
145  pkt->dataDynamic(writeData);
146  pkt->senderState = new ProtocolTester::SenderState(this);
147 
148  // increment the number of outstanding ld_st requests
150 
151  if (!port->sendTimingReq(pkt)) {
152  panic("Not expecting a failed sendTimingReq\n");
153  }
154 
155  // add an outstanding store
156  addOutstandingReqs(outstandingStores, address, lane, location,
157  new_value);
158  }
159  }
160 }
161 
162 void
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  // we use atomic_inc in the tester
174 
175  for (int lane = 0; lane < numLanes; ++lane) {
176  Location location = curAction->getLocation(lane);
177  assert(location >= 0);
178 
179  Addr address = addrManager->getAddress(location);
180 
181  DPRINTF(ProtocolTest, "%s Episode %d: Issuing Atomic_Inc - Addr %s\n",
182  this->getName(), curEpisode->getEpisodeId(),
183  ruby::printAddress(address));
184 
185  // must be aligned with store size
186  assert(address % sizeof(Value) == 0);
187  AtomicOpFunctor *amo_op = new AtomicOpInc<Value>();
188  auto req = std::make_shared<Request>(address, sizeof(Value),
189  flags, tester->requestorId(),
190  0, threadId,
191  AtomicOpFunctorPtr(amo_op));
192  req->setPaddr(address);
193  req->setReqInstSeqNum(tester->getActionSeqNum());
194  // set protocol-specific flags
196 
197  PacketPtr pkt = new Packet(req, MemCmd::SwapReq);
198  uint8_t* data = new uint8_t[sizeof(Value)];
199  pkt->dataDynamic(data);
200  pkt->senderState = new ProtocolTester::SenderState(this);
201 
202  if (!port->sendTimingReq(pkt)) {
203  panic("Not expecting failed sendTimingReq\n");
204  }
205 
206  // increment the number of outstanding atomic ops
208 
209  // add an outstanding atomic
210  addOutstandingReqs(outstandingAtomics, address, lane, location);
211  }
212 }
213 
214 void
216 {
217  DPRINTF(ProtocolTest, "%s Episode %d: Issuing Acquire\n", this->getName(),
219 
220  assert(curAction);
222  // we should not have any outstanding ops at this point
223  assert(pendingFenceCount == 0);
224  assert(pendingLdStCount == 0);
225  assert(pendingAtomicCount == 0);
226 
227  auto acq_req = std::make_shared<Request>(0, 0, 0,
228  tester->requestorId(), 0,
229  threadId, nullptr);
230  acq_req->setPaddr(0);
231  acq_req->setReqInstSeqNum(tester->getActionSeqNum());
232  acq_req->setCacheCoherenceFlags(Request::INV_L1);
233  // set protocol-specific flags
234  setExtraRequestFlags(acq_req);
235 
236  PacketPtr pkt = new Packet(acq_req, MemCmd::MemSyncReq);
237  pkt->senderState = new ProtocolTester::SenderState(this);
238 
239  // increment the number of outstanding fence requests
241 
242  if (!port->sendTimingReq(pkt)) {
243  panic("Not expecting failed sendTimingReq\n");
244  }
245 }
246 
247 void
249 {
250  DPRINTF(ProtocolTest, "%s Episode %d: Issuing Release\n", this->getName(),
252 
253  // A release fence simply waits for all previous stores to complete. All
254  // previous loads and stores were done before this release operation is
255  // issued, so issueReleaseOp is just a no-op in this tester.
256 
257  // we may be able to issue an action. Let's check
258  if (!threadEvent.scheduled()) {
259  scheduleWakeup();
260  }
261 }
262 
263 void
265 {
266  assert(pkt);
267  MemCmd resp_cmd = pkt->cmd;
268  Addr addr = (resp_cmd == MemCmd::WriteCompleteResp) ? 0 : pkt->getAddr();
269 
270  DPRINTF(ProtocolTest, "%s Episode %d: hitCallback - Command %s - "
271  "Addr %s\n", this->getName(),
272  curEpisode->getEpisodeId(), resp_cmd.toString(),
274 
275  // whether the transaction is done after this hitCallback
276  bool isTransactionDone = true;
277 
278  if (resp_cmd == MemCmd::MemSyncResp) {
279  // response to a pending fence
280  // no validation needed for fence responses
281  assert(pendingFenceCount > 0);
282  assert(pendingLdStCount == 0);
283  assert(pendingAtomicCount == 0);
285  } else if (resp_cmd == MemCmd::ReadResp) {
286  // response to a pending read
287  assert(pendingLdStCount > 0);
288  assert(pendingAtomicCount == 0);
289  assert(outstandingLoads.count(addr) > 0);
290 
291  // get return data
292  Value value = *(pkt->getPtr<Value>());
294  validateLoadResp(req.origLoc, req.lane, value);
295 
296  // this Read is done
298  } else if (resp_cmd == MemCmd::WriteResp) {
299  // response to a pending write
300  assert(pendingLdStCount > 0);
301  assert(pendingAtomicCount == 0);
302 
303  // no need to validate Write response
304  // just pop it from the outstanding req table so that subsequent
305  // requests dependent on this write can proceed
306  // note that we don't decrement pendingLdStCount here yet since
307  // the write is not yet completed in downstream memory. Instead, we
308  // decrement the counter when we receive the write completion ack
309  assert(outstandingStores.count(addr) > 0);
312 
313  // update log table
316  req.storedValue,
317  curTick(),
318  cuId);
319 
320  // the transaction is not done yet. Waiting for write completion ack
321  isTransactionDone = false;
322  } else if (resp_cmd == MemCmd::SwapResp) {
323  // response to a pending atomic
324  assert(pendingAtomicCount > 0);
325  assert(pendingLdStCount == 0);
326  assert(outstandingAtomics.count(addr) > 0);
327 
328  // get return data
329  Value value = *(pkt->getPtr<Value>());
330 
331  // validate atomic op return
333  validateAtomicResp(req.origLoc, req.lane, value);
334 
335  // update log table
337  curEpisode->getEpisodeId(), value,
338  curTick(),
339  cuId);
340 
341  // this Atomic is done
343  } else if (resp_cmd == MemCmd::WriteCompleteResp) {
344  // write completion ACK
345  assert(pendingLdStCount > 0);
346  assert(pendingAtomicCount == 0);
347 
348  // the Write is now done
350  } else {
351  panic("Unsupported MemCmd response type");
352  }
353 
354  if (isTransactionDone) {
355  // no need to keep senderState and request around
356  delete pkt->senderState;
357  }
358 
359  delete pkt;
360 
361  // record the last active cycle to check for deadlock
363 
364  // we may be able to issue an action. Let's check
365  if (!threadEvent.scheduled()) {
366  scheduleWakeup();
367  }
368 }
369 
370 void
372 {
373  // No extra request flag is set
374 }
375 
376 } // namespace gem5
gem5::curTick
Tick curTick()
The universal simulation clock.
Definition: cur_tick.hh:46
gem5::TesterThread::TesterThreadEvent::setDesc
void setDesc(std::string _description)
Definition: tester_thread.hh:95
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:495
gem5::GpuWavefront::issueReleaseOp
virtual void issueReleaseOp()
Definition: gpu_wavefront.cc:248
gem5::GpuWavefront::Params
GpuWavefrontParams Params
Definition: gpu_wavefront.hh:47
gem5::GpuWavefront::Value
AddressManager::Value Value
Definition: gpu_wavefront.hh:52
data
const char data[]
Definition: circlebuf.test.cc:48
gem5::Clocked::curCycle
Cycles curCycle() const
Determine the current cycle, corresponding to a tick aligned to a clock edge.
Definition: clocked_object.hh:195
gem5::ruby::printAddress
std::string printAddress(Addr addr)
Definition: Address.cc:80
gem5::GpuWavefront::GpuWavefront
GpuWavefront(const Params &p)
Definition: gpu_wavefront.cc:41
gem5::Episode::Action::Type::STORE
@ STORE
gem5::MemCmd::SwapReq
@ SwapReq
Definition: packet.hh:115
gem5::AtomicOpFunctor
Definition: amo.hh:43
gem5::TesterThread::port
ProtocolTester::SeqPort * port
Definition: tester_thread.hh:148
gem5::TesterThread::curAction
const Episode::Action * curAction
Definition: tester_thread.hh:160
gem5::Episode::Action::getType
Type getType() const
Definition: episode.hh:68
gem5::TesterThread::pendingAtomicCount
int pendingAtomicCount
Definition: tester_thread.hh:165
sc_dt::to_string
const std::string to_string(sc_enc enc)
Definition: sc_fxdefs.cc:91
gem5::TesterThread::pendingFenceCount
int pendingFenceCount
Definition: tester_thread.hh:164
gem5::TesterThread::outstandingAtomics
OutstandingReqTable outstandingAtomics
Definition: tester_thread.hh:176
gem5::MemCmd::SwapResp
@ SwapResp
Definition: packet.hh:116
gem5::AtomicOpInc
Definition: amo.hh:190
gem5::GpuWavefront::cuId
int cuId
Definition: gpu_wavefront.hh:68
gem5::TesterThread::threadEvent
TesterThreadEvent threadEvent
Definition: tester_thread.hh:100
gem5::TesterThread::OutstandingReq::origLoc
Location origLoc
Definition: tester_thread.hh:125
gem5::TesterThread::lastActiveCycle
Cycles lastActiveCycle
Definition: tester_thread.hh:168
gem5::TesterThread
Definition: tester_thread.hh:51
gem5::TesterThread::pendingLdStCount
int pendingLdStCount
Definition: tester_thread.hh:163
gem5::GpuWavefront::issueStoreOps
void issueStoreOps()
Definition: gpu_wavefront.cc:106
gem5::GpuWavefront::Location
AddressManager::Location Location
Definition: gpu_wavefront.hh:51
gem5::MemCmd
Definition: packet.hh:75
gem5::ProtocolTester::requestorId
RequestorID requestorId()
Definition: protocol_tester.hh:124
gem5::Request::ATOMIC_RETURN_OP
@ ATOMIC_RETURN_OP
The request is an atomic that returns data.
Definition: request.hh:173
gem5::TesterThread::getName
const std::string & getName() const
Definition: tester_thread.hh:72
gem5::ArmISA::j
Bitfield< 24 > j
Definition: misc_types.hh:57
gem5::TesterThread::outstandingStores
OutstandingReqTable outstandingStores
Definition: tester_thread.hh:175
gem5::Flags< FlagsType >
gem5::TesterThread::popOutstandingReq
OutstandingReq popOutstandingReq(OutstandingReqTable &req_table, Addr address)
Definition: tester_thread.cc:310
gem5::Request::INV_L1
@ INV_L1
Definition: request.hh:305
gem5::MemCmd::WriteResp
@ WriteResp
Definition: packet.hh:90
DPRINTF
#define DPRINTF(x,...)
Definition: trace.hh:186
gem5::Packet
A Packet is used to encapsulate a transfer between two objects in the memory system (e....
Definition: packet.hh:283
gem5::TesterThread::threadId
int threadId
Definition: tester_thread.hh:138
gem5::probing::Packet
ProbePointArg< PacketInfo > Packet
Packet probe point.
Definition: mem.hh:109
gem5::TesterThread::numLanes
int numLanes
Definition: tester_thread.hh:140
gem5::MipsISA::p
Bitfield< 0 > p
Definition: pra_constants.hh:326
gem5::TesterThread::validateLoadResp
void validateLoadResp(Location loc, int lane, Value ret_val)
Definition: tester_thread.cc:360
gem5::RequestPtr
std::shared_ptr< Request > RequestPtr
Definition: request.hh:92
gem5::MemCmd::ReadReq
@ ReadReq
Definition: packet.hh:86
gem5::MemCmd::MemSyncReq
@ MemSyncReq
Definition: packet.hh:119
gem5::AddressManager::updateLogTable
void updateLogTable(Location loc, int threadId, int episodeId, Value new_value, Tick curTick, int cuId=-1)
Definition: address_manager.cc:415
gem5::ProtocolTester::getActionSeqNum
int getActionSeqNum()
Definition: protocol_tester.hh:139
gem5::GpuWavefront::~GpuWavefront
virtual ~GpuWavefront()
Definition: gpu_wavefront.cc:49
gem5::Episode::Action::Type::ATOMIC
@ ATOMIC
gem5::AddressManager::INVALID_VALUE
static const int INVALID_VALUE
Definition: address_manager.hh:153
gem5::GpuWavefront::setExtraRequestFlags
virtual void setExtraRequestFlags(RequestPtr req)
Definition: gpu_wavefront.cc:371
gem5::Packet::cmd
MemCmd cmd
The command field of the packet.
Definition: packet.hh:361
gem5::Episode::Action::getLocation
Location getLocation(int lane) const
Definition: episode.cc:291
gpu_wavefront.hh
gem5::Addr
uint64_t Addr
Address type This will probably be moved somewhere else in the near future.
Definition: types.hh:147
gem5::TesterThread::addrManager
AddressManager * addrManager
Definition: tester_thread.hh:146
gem5::Packet::senderState
SenderState * senderState
This packet's sender state.
Definition: packet.hh:534
gem5::TesterThread::OutstandingReq::storedValue
Value storedValue
Definition: tester_thread.hh:126
gem5::AddressManager::INVALID_LOCATION
static const int INVALID_LOCATION
Definition: address_manager.hh:154
gem5::TesterThread::OutstandingReq::lane
int lane
Definition: tester_thread.hh:124
gem5::TesterThread::addOutstandingReqs
void addOutstandingReqs(OutstandingReqTable &req_table, Addr addr, int lane, Location loc, Value stored_val=AddressManager::INVALID_VALUE)
Definition: tester_thread.cc:293
gem5::TesterThread::outstandingLoads
OutstandingReqTable outstandingLoads
Definition: tester_thread.hh:174
gem5::MemCmd::toString
const std::string & toString() const
Return the string to a cmd given by idx.
Definition: packet.hh:265
gem5::MemCmd::WriteCompleteResp
@ WriteCompleteResp
Definition: packet.hh:91
gem5::Episode::Action::Type::ACQUIRE
@ ACQUIRE
gem5::GpuWavefront::hitCallback
virtual void hitCallback(PacketPtr pkt)
Definition: gpu_wavefront.cc:264
gem5::TesterThread::curEpisode
Episode * curEpisode
Definition: tester_thread.hh:158
gem5::MemCmd::ReadResp
@ ReadResp
Definition: packet.hh:87
gem5::Packet::dataDynamic
void dataDynamic(T *p)
Set the data pointer to a value that should have delete [] called on it.
Definition: packet.hh:1172
gem5::MemCmd::WriteReq
@ WriteReq
Definition: packet.hh:89
gem5::GpuWavefront::issueAcquireOp
virtual void issueAcquireOp()
Definition: gpu_wavefront.cc:215
gem5::Episode::getEpisodeId
int getEpisodeId() const
Definition: episode.hh:87
gem5::Packet::getAddr
Addr getAddr() const
Definition: packet.hh:781
gem5::AtomicOpFunctorPtr
std::unique_ptr< AtomicOpFunctor > AtomicOpFunctorPtr
Definition: amo.hh:242
gem5::TesterThread::validateAtomicResp
void validateAtomicResp(Location loc, int lane, Value ret_val)
Definition: tester_thread.cc:336
gem5
Reference material can be found at the JEDEC website: UFS standard http://www.jedec....
Definition: decoder.cc:40
gem5::MemCmd::MemSyncResp
@ MemSyncResp
Definition: packet.hh:120
gem5::AddressManager::getLoggedValue
Value getLoggedValue(Location loc) const
Definition: address_manager.cc:423
gem5::GpuWavefront::issueLoadOps
void issueLoadOps()
Definition: gpu_wavefront.cc:55
gem5::TesterThread::OutstandingReq
Definition: tester_thread.hh:122
gem5::TesterThread::tester
ProtocolTester * tester
Definition: tester_thread.hh:144
gem5::TesterThread::threadName
std::string threadName
Definition: tester_thread.hh:142
gem5::TesterThread::scheduleWakeup
void scheduleWakeup()
Definition: tester_thread.cc:114
gem5::Episode::Action::Type::LOAD
@ LOAD
gem5::GpuWavefront::issueAtomicOps
void issueAtomicOps()
Definition: gpu_wavefront.cc:163
gem5::Event::scheduled
bool scheduled() const
Determine if the current event is scheduled.
Definition: eventq.hh:465
panic
#define panic(...)
This implements a cprintf based panic() function.
Definition: logging.hh:177
gem5::AddressManager::getAddress
Addr getAddress(Location loc)
Definition: address_manager.cc:90
gem5::X86ISA::addr
Bitfield< 3 > addr
Definition: types.hh:84
gem5::SenderState
RubyTester::SenderState SenderState
Definition: Check.cc:40
gem5::Packet::getPtr
T * getPtr()
get a pointer to the data ptr.
Definition: packet.hh:1184

Generated on Tue Sep 21 2021 12:25:09 for gem5 by doxygen 1.8.17