dev,dev-hsa,gpu-compute: Refactor dmaVirt calls

Remove the duplicate dmaVirt calls from HSA packet processor and GPU
command processor and move them into their own class. This removes some
duplicate code and allows a DmaVirtDevice to be created which will be
useful for upcoming full system GPU commits.

The DmaVirtDevice is an abstraction of the base DmaDevice but iterates
using ChunkGenerator over virtual addresses. Classes which inherit from
DmaVirtDevice must provide a translation function to translate from
virtual address to physical address. Once translated, the physical
address is passed to DmaDevice to do the work.

Change-Id: Idd59ccb4d9ba21c0b1150ee328ededf5a88d824e
Reviewed-on: https://gem5-review.googlesource.com/c/public/gem5/+/47179
Reviewed-by: Jason Lowe-Power <power.jg@gmail.com>
Reviewed-by: Matt Sinclair <mattdsinclair@gmail.com>
Maintainer: Jason Lowe-Power <power.jg@gmail.com>
Maintainer: Matt Sinclair <mattdsinclair@gmail.com>
Tested-by: kokoro <noreply+kokoro@google.com>
This commit is contained in:
Matthew Poremba
2021-06-23 18:50:58 -05:00
parent 5c7e1bd917
commit 897c0c11ed
8 changed files with 275 additions and 223 deletions

View File

@@ -52,7 +52,7 @@
#include "base/trace.hh"
#include "base/types.hh"
#include "debug/GPUCommandProc.hh"
#include "dev/dma_device.hh"
#include "dev/dma_virt_device.hh"
#include "dev/hsa/hsa_packet_processor.hh"
#include "dev/hsa/hsa_signal.hh"
#include "gpu-compute/dispatcher.hh"
@@ -68,7 +68,7 @@ class GPUComputeDriver;
class GPUDispatcher;
class Shader;
class GPUCommandProcessor : public DmaDevice
class GPUCommandProcessor : public DmaVirtDevice
{
public:
typedef GPUCommandProcessorParams Params;
@@ -79,11 +79,6 @@ class GPUCommandProcessor : public DmaDevice
HSAPacketProcessor& hsaPacketProc();
void dmaReadVirt(Addr host_addr, unsigned size, DmaCallback *cb,
void *data, Tick delay = 0);
void dmaWriteVirt(Addr host_addr, unsigned size, DmaCallback *b,
void *data, Tick delay = 0);
void setShader(Shader *shader);
Shader* shader();
GPUComputeDriver* driver();
@@ -140,36 +135,8 @@ class GPUCommandProcessor : public DmaDevice
typedef void (DmaDevice::*DmaFnPtr)(Addr, int, Event*, uint8_t*, Tick);
void initABI(HSAQueueEntry *task);
HSAPacketProcessor *hsaPP;
void dmaVirt(DmaFnPtr, Addr host_addr, unsigned size, DmaCallback *cb,
void *data, Tick delay = 0);
void translateOrDie(Addr vaddr, Addr &paddr);
/**
* Wraps a std::function object in a DmaCallback. Much cleaner than
* defining a bunch of callback objects for each desired behavior when a
* DMA completes. Contains a built in templated buffer that can be used
* for DMA temporary storage.
*/
template <class T>
class CPDmaCallback : public DmaCallback
{
std::function<void(const T &)> _function;
virtual void
process() override
{
_function(dmaBuffer);
}
public:
T dmaBuffer;
CPDmaCallback(const std::function<void(const T &)> &function,
T dma_buffer_value = 0)
: DmaCallback(), _function(function), dmaBuffer(dma_buffer_value)
{ }
};
/**
* Perform a DMA read of the read_dispatch_id_field_base_byte_offset
* field, which follows directly after the read_dispatch_id (the read
@@ -200,7 +167,7 @@ class GPUCommandProcessor : public DmaDevice
* DMA a copy of the MQD into the task. some fields of
* the MQD will be used to initialize register state in VI
*/
auto *mqdDmaEvent = new CPDmaCallback<int>(
auto *mqdDmaEvent = new DmaVirtCallback<int>(
[ = ] (const int &) { MQDDmaEvent(task); });
dmaReadVirt(task->hostAMDQueueAddr,
@@ -282,7 +249,7 @@ class GPUCommandProcessor : public DmaDevice
* TODO: Technically only need to update private segment fields
* since other MQD entries won't change since we last read them.
*/
auto cb = new CPDmaCallback<int>(
auto cb = new DmaVirtCallback<int>(
[ = ] (const int &) { MQDDmaEvent(task); });
dmaReadVirt(task->hostAMDQueueAddr, sizeof(_amd_queue_t), cb,
@@ -296,7 +263,7 @@ class GPUCommandProcessor : public DmaDevice
task->amdQueue.queue_inactive_signal.handle);
DPRINTF(GPUCommandProc, "Polling queue inactive signal at "
"%p.\n", value_addr);
auto cb = new CPDmaCallback<uint64_t>(
auto cb = new DmaVirtCallback<uint64_t>(
[ = ] (const uint64_t &dma_buffer)
{ WaitScratchDmaEvent(task, dma_buffer); } );
dmaReadVirt(value_addr, sizeof(Addr), cb, &cb->dmaBuffer);