gem5  v20.0.0.2
All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Modules Pages
hsa_packet_processor.hh
Go to the documentation of this file.
1 /*
2  * Copyright (c) 2015-2018 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  * Authors: Eric van Tassell
34  */
35 
36 #ifndef __DEV_HSA_HSA_PACKET_PROCESSOR__
37 #define __DEV_HSA_HSA_PACKET_PROCESSOR__
38 
39 #include <cstdint>
40 
41 #include <queue>
42 
43 #include "dev/dma_device.hh"
44 #include "dev/hsa/hsa.h"
45 #include "dev/hsa/hsa_queue.hh"
46 #include "params/HSAPacketProcessor.hh"
47 
48 #define AQL_PACKET_SIZE 64
49 #define PAGE_SIZE 4096
50 #define NUM_DMA_BUFS 16
51 #define DMA_BUF_SIZE (AQL_PACKET_SIZE * NUM_DMA_BUFS)
52 // HSA runtime supports only 5 signals per barrier packet
53 #define NumSignalsPerBarrier 5
54 
55 class HSADevice;
56 class HWScheduler;
57 
58 // Our internal representation of an HSA queue
60  public:
61  uint64_t basePointer;
62  uint64_t doorbellPointer;
63  uint64_t writeIndex;
64  uint64_t readIndex;
65  uint32_t numElts;
66  uint64_t hostReadIndexPtr;
69 
70  HSAQueueDescriptor(uint64_t base_ptr, uint64_t db_ptr,
71  uint64_t hri_ptr, uint32_t size)
72  : basePointer(base_ptr), doorbellPointer(db_ptr),
73  writeIndex(0), readIndex(0),
74  numElts(size), hostReadIndexPtr(hri_ptr),
75  stalledOnDmaBufAvailability(false),
76  dmaInProgress(false)
77  { }
78  uint64_t spaceRemaining() { return numElts - (writeIndex - readIndex); }
79  uint64_t spaceUsed() { return writeIndex - readIndex; }
80  uint32_t objSize() { return AQL_PACKET_SIZE; }
81  uint32_t numObjs() { return numElts; }
82  bool isFull() { return spaceRemaining() == 0; }
83  bool isEmpty() { return spaceRemaining() == numElts; }
84 
85  uint64_t ptr(uint64_t ix)
86  {
87  return basePointer +
88  ((ix % numElts) * objSize());
89  }
90 };
91 
105 {
106  private:
108  std::string _name;
111  uint64_t _wrIdx; // Points to next write location
112  uint64_t _rdIdx; // Read pointer of AQL buffer
113  uint64_t _dispIdx; // Dispatch pointer of AQL buffer
114 
115  public:
116  std::string name() {return _name;}
117  AQLRingBuffer(uint32_t size, const std::string name);
118  int allocEntry(uint32_t nBufReq);
119  bool freeEntry(void *pkt);
120 
130  void
131  saveHostDispAddr(Addr host_pkt_addr, int num_pkts, int ix)
132  {
133  for (int i = 0; i < num_pkts; ++i) {
134  _hostDispAddresses[ix % numObjs()] = host_pkt_addr + i * objSize();
135  ++ix;
136  }
137  }
138 
139  Addr
140  hostDispAddr() const
141  {
142  return _hostDispAddresses[dispIdx() % numObjs()];
143  }
144 
145  bool
146  dispPending() const
147  {
148  int packet_type = (_aqlBuf[_dispIdx % _aqlBuf.size()].header
150  ((1 << HSA_PACKET_HEADER_WIDTH_TYPE) - 1);
151  return (_dispIdx < _wrIdx) && packet_type != HSA_PACKET_TYPE_INVALID;
152  }
153 
154  uint32_t nFree() const { return _aqlBuf.size() - (_wrIdx - _rdIdx); }
155  void *ptr(uint32_t ix) { return _aqlBuf.data() + (ix % _aqlBuf.size()); }
156  uint32_t numObjs() const { return _aqlBuf.size(); };
157  uint32_t objSize() const { return AQL_PACKET_SIZE; }
158  uint64_t dispIdx() const { return _dispIdx; }
159  uint64_t wrIdx() const { return _wrIdx; }
160  uint64_t rdIdx() const { return _rdIdx; }
161  uint64_t* rdIdxPtr() { return &_rdIdx; }
162  void incRdIdx(uint64_t value) { _rdIdx += value; }
163  void incWrIdx(uint64_t value) { _wrIdx += value; }
164  void incDispIdx(uint64_t value) { _dispIdx += value; }
165 
166 };
167 
168 typedef struct QueueContext {
172  AQLRingBuffer* aql_buf)
173  : qDesc(q_desc), aqlBuf(aql_buf)
174  {}
175  QueueContext() : qDesc(NULL), aqlBuf(NULL) {}
176 } QCntxt;
177 
179 {
180  friend class HWScheduler;
181  protected:
182  typedef void (DmaDevice::*DmaFnPtr)(Addr, int, Event*, uint8_t*, Tick);
185 
186  // Structure to store the read values of dependency signals
187  // from shared memory. Also used for tracking the status of
188  // those reads while they are in progress
190  {
191  public:
193  : pendingReads(0), allRead(false), discardRead(false)
194  {
195  values.resize(NumSignalsPerBarrier);
196  }
197  void handleReadDMA();
199  bool allRead;
200  // If this queue is unmapped when there are pending reads, then
201  // the pending reads has to be discarded.
203  // values stores the value of already read dependency signal
205  void
207  {
208  std::fill(values.begin(), values.end(), 1);
209  }
210  };
211 
212  class QueueProcessEvent : public Event
213  {
214  private:
216  uint32_t rqIdx;
217  public:
218  QueueProcessEvent(HSAPacketProcessor *_hsaPP, uint32_t _rqIdx)
219  : Event(Default_Pri), hsaPP(_hsaPP), rqIdx(_rqIdx)
220  {}
221  virtual void process();
222  virtual const char *description() const;
223  };
224 
225  // Registered queue list entry; each entry has one queueDescriptor and
226  // associated AQL buffer
227  class RQLEntry
228  {
229  public:
230  RQLEntry(HSAPacketProcessor *hsaPP, uint32_t rqIdx)
231  : aqlProcessEvent(hsaPP, rqIdx) {}
233  bool dispPending() { return qCntxt.aqlBuf->dispPending() > 0; }
236  };
237  // Keeps track of queueDescriptors of registered queues
239 
240  void translateOrDie(Addr vaddr, Addr &paddr);
241  void dmaVirt(DmaFnPtr, Addr host_addr, unsigned size, Event *event,
242  void *data, Tick delay = 0);
243 
244  void dmaReadVirt(Addr host_addr, unsigned size, Event *event,
245  void *data, Tick delay = 0);
246 
247  void dmaWriteVirt(Addr host_addr, unsigned size, Event *event,
248  void *data, Tick delay = 0);
249  bool processPkt(void* pkt, uint32_t rl_idx, Addr host_pkt_addr);
250  void displayQueueDescriptor(int pid, uint32_t rl_idx);
251 
252  public:
254  getQueueDesc(uint32_t queId)
255  {
256  return regdQList.at(queId)->qCntxt.qDesc;
257  }
258  class RQLEntry*
259  getRegdListEntry(uint32_t queId)
260  {
261  return regdQList.at(queId);
262  }
263 
265  Addr pioAddr;
266  Addr pioSize;
269 
270  typedef HSAPacketProcessorParams Params;
271  HSAPacketProcessor(const Params *p);
273  void setDeviceQueueDesc(uint64_t hostReadIndexPointer,
274  uint64_t basePointer,
275  uint64_t queue_id,
276  uint32_t size);
277  void unsetDeviceQueueDesc(uint64_t queue_id);
278  void setDevice(HSADevice * dev);
279  void updateReadIndex(int, uint32_t);
280  void getCommandsFromHost(int pid, uint32_t rl_idx);
281 
282  // PIO interface
283  virtual Tick read(Packet*);
284  virtual Tick write(Packet*);
285  virtual AddrRangeList getAddrRanges() const;
286  void finishPkt(void *pkt, uint32_t rl_idx);
287  void finishPkt(void *pkt) { finishPkt(pkt, 0); }
288  void schedAQLProcessing(uint32_t rl_idx);
289 
290  class DepSignalsReadDmaEvent : public Event
291  {
292  protected:
294  public:
296  : Event(Default_Pri, AutoDelete), signalState(ss)
297  {}
298  virtual void process() { signalState->handleReadDMA(); }
299  virtual const char *description() const;
300  };
301 
307  class UpdateReadDispIdDmaEvent : public Event
308  {
309  public:
311 
312  void process() override { }
313  const char *description() const override;
314 
315  };
316 
320  struct dma_series_ctx {
321  // deal with the fact dma ops can complete out of issue order
322  uint32_t pkts_ttl;
323  uint32_t pkts_2_go;
324  uint32_t start_ix;
325  uint32_t rl_idx;
326 
327  dma_series_ctx(uint32_t _pkts_ttl,
328  uint32_t _pkts_2_go,
329  uint32_t _start_ix,
330  uint32_t _rl_idx)
331  : pkts_ttl(_pkts_2_go), pkts_2_go(_pkts_2_go),
332  start_ix(_start_ix), rl_idx(_rl_idx)
333  {};
335  };
336 
337  class CmdQueueCmdDmaEvent : public Event
338  {
339  protected:
341  int pid;
342  bool isRead;
343  uint32_t ix_start;
344  uint num_pkts;
346  void *dest_4debug;
347 
348  public:
349  CmdQueueCmdDmaEvent(HSAPacketProcessor *hsaPP, int pid, bool isRead,
350  uint32_t dma_buf_ix, uint num_bufs,
351  dma_series_ctx *series_ctx, void *dest_4debug);
352  virtual void process();
353  virtual const char *description() const;
354  };
355 };
356 
357 #endif // __DEV_HSA_HSA_PACKET_PROCESSOR__
void incDispIdx(uint64_t value)
RQLEntry(HSAPacketProcessor *hsaPP, uint32_t rqIdx)
const std::string & name()
Definition: trace.cc:50
QueueProcessEvent(HSAPacketProcessor *_hsaPP, uint32_t _rqIdx)
Bitfield< 7 > i
HSAQueueDescriptor(uint64_t base_ptr, uint64_t db_ptr, uint64_t hri_ptr, uint32_t size)
uint64_t wrIdx() const
void * ptr(uint32_t ix)
std::vector< bool > _aqlComplete
uint32_t numObjs() const
#define NumSignalsPerBarrier
dma_series_ctx(uint32_t _pkts_ttl, uint32_t _pkts_2_go, uint32_t _start_ix, uint32_t _rl_idx)
void saveHostDispAddr(Addr host_pkt_addr, int num_pkts, int ix)
the kernel may try to read from the dispatch packet, so we need to keep the host address that corresp...
HSAPacketProcessorParams Params
HSAQueueDescriptor * qDesc
STL vector class.
Definition: stl.hh:37
std::vector< hsa_signal_value_t > values
uint32_t nFree() const
uint64_t Tick
Tick count type.
Definition: types.hh:61
The packet has been processed in the past, but has not been reassigned to the packet processor...
Definition: hsa.h:2728
Addr hostDispAddr() const
bool dispPending() const
Bitfield< 21 > ss
uint64_t Addr
Address type This will probably be moved somewhere else in the near future.
Definition: types.hh:140
A Packet is used to encapsulate a transfer between two objects in the memory system (e...
Definition: packet.hh:249
Bitfield< 10, 5 > event
struct QueueContext QCntxt
std::vector< class RQLEntry * > regdQList
QueueContext(HSAQueueDescriptor *q_desc, AQLRingBuffer *aql_buf)
std::vector< hsa_kernel_dispatch_packet_t > _aqlBuf
void incRdIdx(uint64_t value)
AQLRingBuffer * aqlBuf
void incWrIdx(uint64_t value)
Definition: eventq.hh:246
uint64_t rdIdx() const
#define AQL_PACKET_SIZE
uint64_t dispIdx() const
Internal ring buffer which is used to prefetch/store copies of the in-memory HSA ring buffer...
class RQLEntry * getRegdListEntry(uint32_t queId)
this event is used to update the read_disp_id field (the read pointer) of the MQD, which is how the host code knows the status of the HQD&#39;s read pointer
Packet type.
Definition: hsa.h:2786
Bitfield< 0 > p
HSAQueueDescriptor * getQueueDesc(uint32_t queId)
uint32_t objSize() const
const char data[]
Calls getCurrentEntry once the queueEntry has been dmaRead.
uint64_t ptr(uint64_t ix)
std::vector< Addr > _hostDispAddresses

Generated on Mon Jun 8 2020 15:45:10 for gem5 by doxygen 1.8.13