Loading [MathJax]/jax/output/HTML-CSS/config.js
CIRCT 21.0.0git
All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages
Xrt.cpp
Go to the documentation of this file.
1//===- Xrt.cpp - ESI XRT device backend -------------------------*- C++ -*-===//
2//
3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4// See https://llvm.org/LICENSE.txt for license information.
5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6//
7//===----------------------------------------------------------------------===//
8//
9// DO NOT EDIT!
10// This file is distributed as part of an ESI package. The source for this file
11// should always be modified within CIRCT
12// (lib/dialect/ESI/runtime/cpp/lib/backends/Cosim.cpp).
13//
14//===----------------------------------------------------------------------===//
15
16#include "esi/backends/Xrt.h"
17#include "esi/Services.h"
18
19// XRT includes
20#include "experimental/xrt_bo.h"
21#include "experimental/xrt_device.h"
22#include "experimental/xrt_ip.h"
23#include "experimental/xrt_xclbin.h"
24
25#include <fstream>
26#include <iostream>
27#include <set>
28
29using namespace esi;
30using namespace esi::services;
31using namespace esi::backends::xrt;
32
33/// Parse the connection std::string and instantiate the accelerator. Connection
34/// std::string format:
35/// <xclbin>[:<device_id>]
36/// wherein <device_id> is in BDF format.
37std::unique_ptr<AcceleratorConnection>
38XrtAccelerator::connect(Context &ctxt, std::string connectionString) {
39 std::string xclbin;
40 std::string device_id;
41
42 size_t colon = connectionString.find(':');
43 if (colon == std::string::npos) {
44 xclbin = connectionString;
45 } else {
46 xclbin = connectionString.substr(0, colon);
47 device_id = connectionString.substr(colon + 1);
48 }
49
50 return make_unique<XrtAccelerator>(ctxt, xclbin, device_id);
51}
52
54 constexpr static char kernel_name[] = "esi_kernel";
55
56 Impl(std::string xclbin, std::string device_id) {
57 if (device_id.empty())
58 device = ::xrt::device(0);
59 else
60 device = ::xrt::device(device_id);
61
62 // Find memory group for the host.
63 ::xrt::xclbin xcl(xclbin);
64 std::optional<::xrt::xclbin::mem> host_mem;
65 for (auto mem : xcl.get_mems()) {
66 // The host memory is tagged with "HOST[0]". Memory type is wrong --
67 // reports as DRAM rather than host memory so we can't filter on that.
68 if (mem.get_tag().starts_with("HOST")) {
69 if (host_mem.has_value())
70 throw std::runtime_error("Multiple host memories found in xclbin");
71 else
72 host_mem = mem;
73 }
74 }
75 if (!host_mem)
76 throw std::runtime_error("No host memory found in xclbin");
77 memoryGroup = host_mem->get_index();
78
79 // Load the xclbin and instantiate the IP.
80 auto uuid = device.load_xclbin(xcl);
81 ip = ::xrt::ip(device, uuid, kernel_name);
82 }
83
84 ::xrt::device device;
85 ::xrt::ip ip;
86 int32_t memoryGroup;
87};
88
89/// Construct and connect to a cosim server.
90XrtAccelerator::XrtAccelerator(Context &ctxt, std::string xclbin,
91 std::string device_id)
92 : AcceleratorConnection(ctxt) {
93 impl = make_unique<Impl>(xclbin, device_id);
94}
96
97namespace {
98/// Implementation of MMIO for XRT. Uses an indirect register to access a
99/// virtual MMIO space since Vivado/Vitis don't support large enough MMIO
100/// spaces.
101class XrtMMIO : public MMIO {
102
103 // Physical register to write the virtual address.
104 constexpr static uint32_t IndirectLocation = 0x18;
105 // Physical register to read/write the virtual MMIO address stored at
106 // `IndirectLocation`.
107 constexpr static uint32_t IndirectMMIOReg = 0x20;
108
109public:
110 XrtMMIO(XrtAccelerator &conn, ::xrt::ip &ip, const HWClientDetails &clients)
111 : MMIO(conn, clients), ip(ip) {}
112
113 uint64_t read(uint32_t addr) const override {
114 std::lock_guard<std::mutex> lock(m);
115
116 // Write the address to the indirect location register.
117 xrt_write(IndirectLocation, addr);
118 // Read from the indirect register.
119 uint64_t ret = xrt_read(IndirectMMIOReg);
120
121 getConnection().getLogger().debug(
122 [addr, ret](std::string &subsystem, std::string &msg,
123 std::unique_ptr<std::map<std::string, std::any>> &details) {
124 subsystem = "xrt_mmio";
125 msg = "MMIO[0x" + toHex(addr) + "] = 0x" + toHex(ret);
126 });
127 return ret;
128 }
129 void write(uint32_t addr, uint64_t data) override {
130 std::lock_guard<std::mutex> lock(m);
131
132 // Write the address to the indirect location register.
133 xrt_write(IndirectLocation, addr);
134 // Write to the indirect register.
135 xrt_write(IndirectMMIOReg, data);
136
137 conn.getLogger().debug(
138 [addr,
139 data](std::string &subsystem, std::string &msg,
140 std::unique_ptr<std::map<std::string, std::any>> &details) {
141 subsystem = "xrt_mmio";
142 msg = "MMIO[0x" + toHex(addr) + "] <- 0x" + toHex(data);
143 });
144 }
145
146 /// Read a physical register.
147 uint64_t xrt_read(uint32_t addr) const {
148 auto lo = static_cast<uint64_t>(ip.read_register(addr));
149 auto hi = static_cast<uint64_t>(ip.read_register(addr + 0x4));
150 return (hi << 32) | lo;
151 }
152 /// Write a physical register.
153 void xrt_write(uint32_t addr, uint64_t data) const {
154 ip.write_register(addr, data);
155 ip.write_register(addr + 0x4, data >> 32);
156 }
157
158private:
159 ::xrt::ip &ip;
160 mutable std::mutex m;
161};
162} // namespace
163
164namespace {
165/// Host memory service specialized to XRT.
166class XrtHostMem : public HostMem {
167public:
168 XrtHostMem(XrtAccelerator &conn, ::xrt::device &device, int32_t memoryGroup)
169 : HostMem(conn), device(device), memoryGroup(memoryGroup) {}
170
171 struct XrtHostMemRegion : public HostMemRegion {
172 XrtHostMemRegion(::xrt::device &device, std::size_t size,
173 HostMem::Options opts, int32_t memoryGroup) {
174 bo = ::xrt::bo(device, size, ::xrt::bo::flags::host_only, memoryGroup);
175 // Map the buffer into application memory space so that the application
176 // can use it just like any memory -- no need to use bo::write.
177 ptr = bo.map();
178 }
179 virtual void *getPtr() const override { return ptr; }
180 /// On XRT platforms, the pointer which the device sees is different from
181 /// the pointer the user application sees.
182 virtual void *getDevicePtr() const override { return (void *)bo.address(); }
183 virtual std::size_t getSize() const override { return bo.size(); }
184 /// It is required to use 'sync' to flush the caches before executing any
185 /// DMA.
186 virtual void flush() override { bo.sync(XCL_BO_SYNC_BO_TO_DEVICE); }
187
188 private:
189 ::xrt::bo bo;
190 void *ptr;
191 };
192
193 std::unique_ptr<HostMemRegion>
194 allocate(std::size_t size, HostMem::Options opts) const override {
195 return std::unique_ptr<HostMemRegion>(
196 new XrtHostMemRegion(device, size, opts, memoryGroup));
197 }
198
199private:
200 ::xrt::device &device;
201 int32_t memoryGroup;
202};
203} // namespace
204
206 std::string implName,
207 const ServiceImplDetails &details,
208 const HWClientDetails &clients) {
209 if (svcType == typeid(MMIO))
210 return new XrtMMIO(*this, impl->ip, clients);
211 else if (svcType == typeid(HostMem))
212 return new XrtHostMem(*this, impl->device, impl->memoryGroup);
213 else if (svcType == typeid(SysInfo))
214 return new MMIOSysInfo(getService<MMIO>());
215 return nullptr;
216}
217
#define REGISTER_ACCELERATOR(Name, TAccelerator)
Abstract class representing a connection to an accelerator.
Definition Accelerator.h:79
virtual void disconnect()
Disconnect from the accelerator cleanly.
Context & ctxt
ESI accelerator context.
AcceleratorConnections, Accelerators, and Manifests must all share a context.
Definition Context.h:31
Connect to an ESI simulation.
Definition Xrt.h:31
XrtAccelerator(Context &, std::string xclbin, std::string kernelName)
Construct and connect to a cosim server.
Definition Xrt.cpp:90
static std::unique_ptr< AcceleratorConnection > connect(Context &, std::string connectionString)
Parse the connection std::string and instantiate the accelerator.
Definition Xrt.cpp:38
std::unique_ptr< Impl > impl
Definition Xrt.h:47
virtual Service * createService(Service::Type service, AppIDPath path, std::string implName, const ServiceImplDetails &details, const HWClientDetails &clients) override
Called by getServiceImpl exclusively.
Definition Xrt.cpp:205
Implement the SysInfo API for a standard MMIO protocol.
Definition Services.h:184
Parent class of all APIs modeled as 'services'.
Definition Services.h:46
const std::type_info & Type
Definition Services.h:48
Information about the Accelerator system.
Definition Services.h:100
Definition esi.py:1
std::map< std::string, std::any > ServiceImplDetails
Definition Common.h:98
std::string toHex(void *val)
Definition Common.cpp:37
std::vector< HWClientDetail > HWClientDetails
Definition Common.h:97
static constexpr char kernel_name[]
Definition Xrt.cpp:54
Impl(std::string xclbin, std::string device_id)
Definition Xrt.cpp:56
Options for allocating host memory.
Definition Services.h:226