Matthew Poremba has uploaded this change for review. ( https://gem5-review.googlesource.com/c/public/gem5/+/44909 )

Change subject: dev-amdgpu: Add initial AMDGPU device
......................................................................

dev-amdgpu: Add initial AMDGPU device

The initial device contains enough code for the gpufs configuration
scripts to register an amdgpu device that identifies as a Vega 10
(Frontier Edition) device when PCI devices are listed by Linux. It also
contains stubs necessary for adding the MMIO interface to handle driver
initialization.

Using the configuration Linux boots and the device is successfully seen
in lspci. The driver can also begin loading an successfully sends
initial MMIOs and attempts to read the ROM.

Change-Id: I7ad87026876f31f44668e700d5adb639c2c053c1
---
A src/dev/amdgpu/AMDGPU.py
A src/dev/amdgpu/SConscript
A src/dev/amdgpu/amdgpu_device.cc
A src/dev/amdgpu/amdgpu_device.hh
4 files changed, 463 insertions(+), 0 deletions(-)



diff --git a/src/dev/amdgpu/AMDGPU.py b/src/dev/amdgpu/AMDGPU.py
new file mode 100644
index 0000000..951c833
--- /dev/null
+++ b/src/dev/amdgpu/AMDGPU.py
@@ -0,0 +1,75 @@
+# Copyright (c) 2021 Advanced Micro Devices, Inc.
+# All rights reserved.
+#
+# For use for simulation and test purposes only
+#
+# 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.
+
+from m5.params import *
+from m5.objects.PciDevice import PciDevice
+from m5.objects.PciDevice import PciMemBar, PciMemUpperBar, PciLegacyIoBar
+
+class AMDGPUDevice(PciDevice):
+    type = 'AMDGPUDevice'
+    cxx_header = "dev/amdgpu/amdgpu_device.hh"
+
+    # IDs for AMD Vega 10
+    VendorID = 0x1002
+    DeviceID = 0x6863
+ # Command 0x3 never gets sent indicating IO and Mem bars are enabled. Hard
+    # code the command here and deal unassigned BARs on C++ side.
+    Command = 0x3
+    Status = 0x0280
+    Revision = 0x0
+    ClassCode = 0x03
+    SubClassCode = 0x00
+    ProgIF = 0x00
+
+    # This does not work but I believe it is supposed to:
+ #BARs = (PciMemBar(size='16GiB'), PciMemUpperBar(), PciMemBar(size='2MiB'),
+    #        PciMemUpperBar(), PciLegacyIoBar(addr = 0xf000, size='256B'),
+    #        PciMemBar(size='512KiB'))
+    BAR0 = PciMemBar(size='16GiB')
+    BAR1 = PciMemUpperBar()
+    BAR2 = PciMemBar(size='2MiB')
+    BAR3 = PciMemUpperBar()
+    BAR4 = PciLegacyIoBar(addr=0xf000, size='256B')
+    BAR5 = PciMemBar(size='512KiB')
+
+    InterruptLine = 14
+    InterruptPin = 2
+    ExpansionROM = 0
+
+    RomBin = Param.String("/i/dont/exist",
+                          "ROM binary dumped from hardware")
+    traceFile = Param.String("/i/dont/exist",
+                             "MMIO trace collected on hardware")
+
+    def setTraceFile(self, trace):
+        self.traceFile = trace
+    def setRomBin(self, rom):
+        self.RomBin = rom
diff --git a/src/dev/amdgpu/SConscript b/src/dev/amdgpu/SConscript
new file mode 100644
index 0000000..dcd2d30
--- /dev/null
+++ b/src/dev/amdgpu/SConscript
@@ -0,0 +1,42 @@
+# Copyright (c) 2021 Advanced Micro Devices, Inc.
+# All rights reserved.
+#
+# For use for simulation and test purposes only
+#
+# 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.
+
+Import('*')
+
+if env['TARGET_ISA'] == 'null' or not env['BUILD_GPU']:
+    Return()
+
+# Controllers
+SimObject('AMDGPU.py')
+
+Source('amdgpu_device.cc')
+
+DebugFlag('AMDGPUDevice')
diff --git a/src/dev/amdgpu/amdgpu_device.cc b/src/dev/amdgpu/amdgpu_device.cc
new file mode 100644
index 0000000..d1aa06a
--- /dev/null
+++ b/src/dev/amdgpu/amdgpu_device.cc
@@ -0,0 +1,239 @@
+/*
+ * Copyright (c) 2021 Advanced Micro Devices, Inc.
+ * All rights reserved.
+ *
+ * For use for simulation and test purposes only
+ *
+ * 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.
+ */
+
+#include "dev/amdgpu/amdgpu_device.hh"
+
+#include "debug/AMDGPUDevice.hh"
+#include "mem/packet.hh"
+#include "mem/packet_access.hh"
+#include "params/AMDGPUDevice.hh"
+#include "sim/byteswap.hh"
+
+AMDGPUDevice::AMDGPUDevice(const AMDGPUDeviceParams &p)
+    : PciDevice(p), romBin(0)
+{
+    // Loading the rom binary dumped from hardware.
+    romBin.open(p.RomBin, std::ios::binary);
+    romBin.read(rom.data(), ROMSize);
+    romBin.close();
+
+    if (config.expansionROM) {
+        romRange = RangeSize(config.expansionROM, ROMSize);
+    } else {
+        romRange = RangeSize(VGA_ROM_DEFAULT, ROMSize);
+    }
+}
+
+void
+AMDGPUDevice::readROM(PacketPtr pkt)
+{
+    Addr rom_offset = pkt->getAddr() & (ROMSize - 1);
+    uint64_t rom_data = 0;
+
+    memcpy(&rom_data, rom.data() + rom_offset, pkt->getSize());
+    pkt->setUintX(rom_data, ByteOrder::little);
+
+ DPRINTF(AMDGPUDevice, "Read from addr %#x on ROM offset %#x data: %#x\n",
+            pkt->getAddr(), rom_offset, rom_data);
+}
+
+AddrRangeList
+AMDGPUDevice::getAddrRanges() const
+{
+    AddrRangeList ranges = PciDevice::getAddrRanges();
+    AddrRangeList ret_ranges;
+    ret_ranges.push_back(romRange);
+
+    // If the range starts at zero assume OS hasn't assigned it yet. Do not
+    // return ranges starting with zero as they will surely overlap with
+    // another range causing the I/O crossbar to fatal.
+    for (auto & r : ranges) {
+        if (r.start() != 0) {
+            ret_ranges.push_back(r);
+        }
+    }
+
+    return ret_ranges;
+}
+
+Tick
+AMDGPUDevice::readConfig(PacketPtr pkt)
+{
+    M5_VAR_USED int offset = pkt->getAddr() & PCI_CONFIG_SIZE;
+    DPRINTF(AMDGPUDevice, "Read Config: from offset: %#x size: %#x "
+            "data: %#x\n", offset, pkt->getSize(), config.data[offset]);
+
+    return PciDevice::readConfig(pkt);
+}
+
+Tick
+AMDGPUDevice::writeConfig(PacketPtr pkt)
+{
+    int offset = pkt->getAddr() & PCI_CONFIG_SIZE;
+    uint32_t data;
+    if (pkt->getSize() == 1)
+        data = pkt->getLE<uint8_t>();
+    else if (pkt->getSize() == 2)
+        data = pkt->getLE<uint16_t>();
+    else
+        data = pkt->getLE<uint32_t>();
+
+    DPRINTF(AMDGPUDevice, "Write Config: from offset: %#x size: %#x "
+            "data: %#x\n", offset, pkt->getSize(), data);
+
+    return PciDevice::writeConfig(pkt);
+}
+
+void
+AMDGPUDevice::dispatchAccess(PacketPtr pkt, bool read)
+{
+    M5_VAR_USED uint32_t data;
+    data = pkt->getUintX(ByteOrder::little);
+
+    DPRINTF(AMDGPUDevice, "%s from addr %#x size: %#x data: %#x\n",
+            read ? "Read" : "Write", pkt->getAddr(), pkt->getSize(), data);
+
+    pkt->makeAtomicResponse();
+}
+
+void
+AMDGPUDevice::readFrame(PacketPtr pkt, Addr offset)
+{
+    DPRINTF(AMDGPUDevice, "Read framebuffer address %#lx\n", offset);
+}
+
+void
+AMDGPUDevice::readDoorbell(PacketPtr pkt, Addr offset)
+{
+    DPRINTF(AMDGPUDevice, "Read doorbell %#lx\n", offset);
+}
+
+void
+AMDGPUDevice::readMmio(PacketPtr pkt, Addr offset)
+{
+    DPRINTF(AMDGPUDevice, "Read MMIO %#lx\n", offset);
+}
+
+void
+AMDGPUDevice::writeFrame(PacketPtr pkt, Addr offset)
+{
+    DPRINTF(AMDGPUDevice, "Wrote framebuffer address %#lx\n", offset);
+}
+
+void
+AMDGPUDevice::writeDoorbell(PacketPtr pkt, Addr offset)
+{
+    DPRINTF(AMDGPUDevice, "Wrote doorbell %#lx\n", offset);
+}
+
+void
+AMDGPUDevice::writeMmio(PacketPtr pkt, Addr offset)
+{
+    DPRINTF(AMDGPUDevice, "Wrote MMIO %#lx\n", offset);
+}
+
+Tick
+AMDGPUDevice::read(PacketPtr pkt)
+{
+    if (isROM(pkt->getAddr())) {
+        readROM(pkt);
+    } else {
+        int barnum = -1;
+        Addr offset = 0;
+        getBAR(pkt->getAddr(), barnum, offset);
+
+        switch (barnum) {
+          case 0:
+              readFrame(pkt, offset);
+              break;
+          case 2:
+              readDoorbell(pkt, offset);
+              break;
+          case 5:
+              readMmio(pkt, offset);
+              break;
+          default:
+            panic("Request with address out of mapped range!");
+        }
+    }
+
+    dispatchAccess(pkt, true);
+    return pioDelay;
+}
+
+Tick
+AMDGPUDevice::write(PacketPtr pkt)
+{
+    int barnum = -1;
+    Addr offset = 0;
+    getBAR(pkt->getAddr(), barnum, offset);
+
+    switch (barnum) {
+      case 0:
+          writeFrame(pkt, offset);
+          break;
+      case 2:
+          writeDoorbell(pkt, offset);
+          break;
+      case 5:
+          writeMmio(pkt, offset);
+          break;
+      default:
+        panic("Request with address out of mapped range!");
+    }
+
+ // Record only if there is non-zero value, or a value to be overwritten.
+    // Reads return 0 by default.
+    uint64_t data = pkt->getUintX(ByteOrder::little);
+
+    if (data || regs.find(pkt->getAddr()) != regs.end())
+        regs[pkt->getAddr()] = data;
+
+    dispatchAccess(pkt, false);
+
+    return pioDelay;
+}
+
+void
+AMDGPUDevice::serialize(CheckpointOut &cp) const
+{
+    // Serialize the PciDevice base class
+    PciDevice::serialize(cp);
+}
+
+void
+AMDGPUDevice::unserialize(CheckpointIn &cp)
+{
+    // Unserialize the PciDevice base class
+    PciDevice::unserialize(cp);
+}
diff --git a/src/dev/amdgpu/amdgpu_device.hh b/src/dev/amdgpu/amdgpu_device.hh
new file mode 100644
index 0000000..1471d79
--- /dev/null
+++ b/src/dev/amdgpu/amdgpu_device.hh
@@ -0,0 +1,107 @@
+/*
+ * Copyright (c) 2021 Advanced Micro Devices, Inc.
+ * All rights reserved.
+ *
+ * For use for simulation and test purposes only
+ *
+ * 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 <fstream>
+#include <map>
+
+#include "base/bitunion.hh"
+#include "dev/io_device.hh"
+#include "dev/pci/device.hh"
+#include "params/AMDGPUDevice.hh"
+
+// By default (no expansion enabled), X86 kernel expects the vga ROM at 0xc0000
+constexpr uint32_t VGA_ROM_DEFAULT = 0xc0000;
+constexpr uint32_t ROMSize = 0x20000;        // 128kB
+
+/**
+ * Device model for an AMD GPU
+ */
+class AMDGPUDevice : public PciDevice
+{
+  private:
+    void dispatchAccess(PacketPtr pkt, bool read);
+
+    /**
+     * Methods to handle specific BAR read/writes
+     */
+    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);
+
+    /**
+     * VGA ROM methods
+     */
+    AddrRange romRange;
+    bool isROM(Addr addr) const { return romRange.contains(addr); }
+    void readROM(PacketPtr pkt);
+
+    std::array<char, ROMSize> rom;
+    std::ifstream romBin;
+
+    /**
+     * Device registers
+     */
+    std::unordered_map<uint32_t, uint64_t> regs;
+
+  public:
+    //const Params *params() const { return (const Params *)_params; }
+    AMDGPUDevice(const AMDGPUDeviceParams &p);
+
+    /**
+     * PciDevice methods
+     */
+    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;
+};
+
+#endif // __DEV_AMDGPU_AMDGPU_DEVICE_HH__

--
To view, visit https://gem5-review.googlesource.com/c/public/gem5/+/44909
To unsubscribe, or for help writing mail filters, visit https://gem5-review.googlesource.com/settings

Gerrit-Project: public/gem5
Gerrit-Branch: develop
Gerrit-Change-Id: I7ad87026876f31f44668e700d5adb639c2c053c1
Gerrit-Change-Number: 44909
Gerrit-PatchSet: 1
Gerrit-Owner: Matthew Poremba <matthew.pore...@amd.com>
Gerrit-MessageType: newchange
_______________________________________________
gem5-dev mailing list -- gem5-dev@gem5.org
To unsubscribe send an email to gem5-dev-le...@gem5.org
%(web_page_url)slistinfo%(cgiext)s/%(_internal_name)s

Reply via email to