Currently the amdgpu simulated device is assumed to be a Vega10. As a result there are a few things that are hardcoded. One of those is the number of SDMAs. In order to add a newer device, such as MI100+, we need to enable a flexible number of SDMAs. In order to support a variable number of SDMAs and with the MMIO offsets of each device being potentially different, the MMIO interface for SDMAs is changed to use an SDMA class method dispatch table with forwards a 32-bit value from the MMIO packet to the MMIO functions in SDMA of the format `void method(uint32_t)`. Several changes are made to enable this: - Allow the SDMA to have a variable MMIO base and size. These are configured in python. - An SDMA class method dispatch table which contains the MMIO offset relative to the SDMA's MMIO base address. - An updated writeMMIO method to iterate over the SDMA MMIO address ranges and call the appropriate SDMA MMIO method which matches the MMIO offset. - Moved all SDMA related MMIO data bit twiddling, masking, etc. into the MMIO methods themselves instead of in the writeMMIO method in SDMAEngine. Change-Id: Ifce626f84d52f9e27e4438ba4e685e30dbf06dbc Reviewed-on: https://gem5-review.googlesource.com/c/public/gem5/+/70040 Maintainer: Matt Sinclair <mattdsinclair@gmail.com> Tested-by: kokoro <noreply+kokoro@google.com> Reviewed-by: Matt Sinclair <mattdsinclair@gmail.com>
211 lines
6.8 KiB
C++
211 lines
6.8 KiB
C++
/*
|
|
* Copyright (c) 2021 Advanced Micro Devices, Inc.
|
|
* All rights reserved.
|
|
*
|
|
* Redistribution and use in source and binary forms, with or without
|
|
* modification, are permitted provided that the following conditions are met:
|
|
*
|
|
* 1. Redistributions of source code must retain the above copyright notice,
|
|
* this list of conditions and the following disclaimer.
|
|
*
|
|
* 2. Redistributions in binary form must reproduce the above copyright notice,
|
|
* this list of conditions and the following disclaimer in the documentation
|
|
* and/or other materials provided with the distribution.
|
|
*
|
|
* 3. Neither the name of the copyright holder nor the names of its
|
|
* contributors may be used to endorse or promote products derived from this
|
|
* software without specific prior written permission.
|
|
*
|
|
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
|
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
|
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
|
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
|
|
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
|
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
|
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
|
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
|
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
|
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
|
* POSSIBILITY OF SUCH DAMAGE.
|
|
*/
|
|
|
|
#ifndef __DEV_AMDGPU_AMDGPU_DEVICE_HH__
|
|
#define __DEV_AMDGPU_AMDGPU_DEVICE_HH__
|
|
|
|
#include <map>
|
|
|
|
#include "base/bitunion.hh"
|
|
#include "dev/amdgpu/amdgpu_defines.hh"
|
|
#include "dev/amdgpu/amdgpu_vm.hh"
|
|
#include "dev/amdgpu/memory_manager.hh"
|
|
#include "dev/amdgpu/mmio_reader.hh"
|
|
#include "dev/io_device.hh"
|
|
#include "dev/pci/device.hh"
|
|
#include "params/AMDGPUDevice.hh"
|
|
|
|
namespace gem5
|
|
{
|
|
|
|
class AMDGPUInterruptHandler;
|
|
class SDMAEngine;
|
|
|
|
/**
|
|
* Device model for an AMD GPU. This models the interface between the PCI bus
|
|
* and the various IP blocks behind it. It translates requests to the various
|
|
* BARs and sends them to the appropriate IP block. BAR0 requests are VRAM
|
|
* requests that go to device memory, BAR2 are doorbells which are decoded and
|
|
* sent to the corresponding IP block. BAR5 is the MMIO interface which writes
|
|
* data values to registers controlling the IP blocks.
|
|
*/
|
|
class AMDGPUDevice : public PciDevice
|
|
{
|
|
private:
|
|
/**
|
|
* Convert a PCI packet into a response
|
|
*/
|
|
void dispatchAccess(PacketPtr pkt, bool read);
|
|
|
|
/**
|
|
* Helper methods to handle specific BAR read/writes. Offset is the
|
|
* address of the packet - base address of the BAR.
|
|
*
|
|
* read/writeFrame are used for BAR0 requests
|
|
* read/writeDoorbell are used for BAR2 requests
|
|
* read/writeMMIO are used for BAR5 requests
|
|
*/
|
|
void readFrame(PacketPtr pkt, Addr offset);
|
|
void readDoorbell(PacketPtr pkt, Addr offset);
|
|
void readMMIO(PacketPtr pkt, Addr offset);
|
|
|
|
void writeFrame(PacketPtr pkt, Addr offset);
|
|
void writeDoorbell(PacketPtr pkt, Addr offset);
|
|
void writeMMIO(PacketPtr pkt, Addr offset);
|
|
|
|
/**
|
|
* Structures to hold registers, doorbells, and some frame memory
|
|
*/
|
|
using GPURegMap = std::unordered_map<uint32_t, uint64_t>;
|
|
GPURegMap regs;
|
|
std::unordered_map<uint32_t, QueueType> doorbells;
|
|
|
|
/**
|
|
* VGA ROM methods
|
|
*/
|
|
AddrRange romRange;
|
|
bool isROM(Addr addr) const { return romRange.contains(addr); }
|
|
void readROM(PacketPtr pkt);
|
|
void writeROM(PacketPtr pkt);
|
|
|
|
std::array<uint8_t, ROM_SIZE> rom;
|
|
|
|
/**
|
|
* MMIO reader to populate device registers map.
|
|
*/
|
|
AMDMMIOReader mmioReader;
|
|
|
|
/**
|
|
* Blocks of the GPU
|
|
*/
|
|
AMDGPUMemoryManager *gpuMemMgr;
|
|
AMDGPUInterruptHandler *deviceIH;
|
|
AMDGPUVM gpuvm;
|
|
PM4PacketProcessor *pm4PktProc;
|
|
GPUCommandProcessor *cp;
|
|
|
|
// SDMAs mapped by doorbell offset
|
|
std::unordered_map<uint32_t, SDMAEngine *> sdmaEngs;
|
|
// SDMAs mapped by ID
|
|
std::unordered_map<uint32_t, SDMAEngine *> sdmaIds;
|
|
// SDMA ID to MMIO range
|
|
std::unordered_map<uint32_t, AddrRange> sdmaMmios;
|
|
// SDMA ID to function
|
|
typedef void (SDMAEngine::*sdmaFuncPtr)(uint32_t);
|
|
std::unordered_map<uint32_t, sdmaFuncPtr> sdmaFunc;
|
|
|
|
/**
|
|
* Initial checkpoint support variables.
|
|
*/
|
|
bool checkpoint_before_mmios;
|
|
int init_interrupt_count;
|
|
|
|
// VMIDs data structures
|
|
// map of pasids to vmids
|
|
std::unordered_map<uint16_t, uint16_t> idMap;
|
|
// map of doorbell offsets to vmids
|
|
std::unordered_map<Addr, uint16_t> doorbellVMIDMap;
|
|
// map of vmid to all queue ids using that vmid
|
|
std::unordered_map<uint16_t, std::set<int>> usedVMIDs;
|
|
// last vmid allocated by map_process PM4 packet
|
|
uint16_t _lastVMID;
|
|
|
|
/*
|
|
* Backing store for GPU memory / framebuffer / VRAM
|
|
*/
|
|
memory::PhysicalMemory deviceMem;
|
|
|
|
public:
|
|
AMDGPUDevice(const AMDGPUDeviceParams &p);
|
|
|
|
/**
|
|
* Methods inherited from PciDevice
|
|
*/
|
|
void intrPost();
|
|
|
|
Tick writeConfig(PacketPtr pkt) override;
|
|
Tick readConfig(PacketPtr pkt) override;
|
|
|
|
Tick read(PacketPtr pkt) override;
|
|
Tick write(PacketPtr pkt) override;
|
|
|
|
AddrRangeList getAddrRanges() const override;
|
|
|
|
/**
|
|
* Checkpoint support
|
|
*/
|
|
void serialize(CheckpointOut &cp) const override;
|
|
void unserialize(CheckpointIn &cp) override;
|
|
|
|
/**
|
|
* Get handles to GPU blocks.
|
|
*/
|
|
AMDGPUInterruptHandler* getIH() { return deviceIH; }
|
|
SDMAEngine* getSDMAById(int id);
|
|
SDMAEngine* getSDMAEngine(Addr offset);
|
|
AMDGPUVM &getVM() { return gpuvm; }
|
|
AMDGPUMemoryManager* getMemMgr() { return gpuMemMgr; }
|
|
GPUCommandProcessor* CP() { return cp; }
|
|
|
|
/**
|
|
* Set handles to GPU blocks.
|
|
*/
|
|
void setDoorbellType(uint32_t offset, QueueType qt);
|
|
void setSDMAEngine(Addr offset, SDMAEngine *eng);
|
|
|
|
/**
|
|
* Register value getter/setter. Used by other GPU blocks to change
|
|
* values from incoming driver/user packets.
|
|
*/
|
|
uint32_t getRegVal(uint32_t addr);
|
|
void setRegVal(uint32_t addr, uint32_t value);
|
|
|
|
/**
|
|
* Methods related to translations and system/device memory.
|
|
*/
|
|
RequestorID vramRequestorId() { return gpuMemMgr->getRequestorID(); }
|
|
|
|
/* HW context stuff */
|
|
uint16_t lastVMID() { return _lastVMID; }
|
|
uint16_t allocateVMID(uint16_t pasid);
|
|
void deallocateVmid(uint16_t vmid);
|
|
void deallocatePasid(uint16_t pasid);
|
|
void deallocateAllQueues();
|
|
void mapDoorbellToVMID(Addr doorbell, uint16_t vmid);
|
|
uint16_t getVMID(Addr doorbell) { return doorbellVMIDMap[doorbell]; }
|
|
std::unordered_map<uint16_t, std::set<int>>& getUsedVMIDs();
|
|
void insertQId(uint16_t vmid, int id);
|
|
};
|
|
|
|
} // namespace gem5
|
|
|
|
#endif // __DEV_AMDGPU_AMDGPU_DEVICE_HH__
|