CIRCT 22.0.0git
Loading...
Searching...
No Matches
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 AppIDPath &idPath,
111 const HWClientDetails &clients)
112 : MMIO(conn, idPath, clients), ip(ip) {}
113
114 uint64_t read(uint32_t addr) const override {
115 std::lock_guard<std::mutex> lock(m);
116
117 // Write the address to the indirect location register.
118 xrt_write(IndirectLocation, addr);
119 // Read from the indirect register.
120 uint64_t ret = xrt_read(IndirectMMIOReg);
121
122 getConnection().getLogger().debug(
123 [addr, ret](std::string &subsystem, std::string &msg,
124 std::unique_ptr<std::map<std::string, std::any>> &details) {
125 subsystem = "xrt_mmio";
126 msg = "MMIO[0x" + toHex(addr) + "] = 0x" + toHex(ret);
127 });
128 return ret;
129 }
130 void write(uint32_t addr, uint64_t data) override {
131 std::lock_guard<std::mutex> lock(m);
132
133 // Write the address to the indirect location register.
134 xrt_write(IndirectLocation, addr);
135 // Write to the indirect register.
136 xrt_write(IndirectMMIOReg, data);
137
138 conn.getLogger().debug(
139 [addr,
140 data](std::string &subsystem, std::string &msg,
141 std::unique_ptr<std::map<std::string, std::any>> &details) {
142 subsystem = "xrt_mmio";
143 msg = "MMIO[0x" + toHex(addr) + "] <- 0x" + toHex(data);
144 });
145 }
146
147 /// Read a physical register.
148 uint64_t xrt_read(uint32_t addr) const {
149 auto lo = static_cast<uint64_t>(ip.read_register(addr));
150 auto hi = static_cast<uint64_t>(ip.read_register(addr + 0x4));
151 return (hi << 32) | lo;
152 }
153 /// Write a physical register.
154 void xrt_write(uint32_t addr, uint64_t data) const {
155 ip.write_register(addr, data);
156 ip.write_register(addr + 0x4, data >> 32);
157 }
158
159private:
160 ::xrt::ip &ip;
161 mutable std::mutex m;
162};
163} // namespace
164
165namespace {
166/// Host memory service specialized to XRT.
167class XrtHostMem : public HostMem {
168public:
169 XrtHostMem(XrtAccelerator &conn, ::xrt::device &device, int32_t memoryGroup)
170 : HostMem(conn), device(device), memoryGroup(memoryGroup) {}
171
172 struct XrtHostMemRegion : public HostMemRegion {
173 XrtHostMemRegion(::xrt::device &device, std::size_t size,
174 HostMem::Options opts, int32_t memoryGroup) {
175 bo = ::xrt::bo(device, size, ::xrt::bo::flags::host_only, memoryGroup);
176 // Map the buffer into application memory space so that the application
177 // can use it just like any memory -- no need to use bo::write.
178 ptr = bo.map();
179 }
180 virtual void *getPtr() const override { return ptr; }
181 /// On XRT platforms, the pointer which the device sees is different from
182 /// the pointer the user application sees.
183 virtual void *getDevicePtr() const override { return (void *)bo.address(); }
184 virtual std::size_t getSize() const override { return bo.size(); }
185 /// It is required to use 'sync' to flush the caches before executing any
186 /// DMA.
187 virtual void flush() override { bo.sync(XCL_BO_SYNC_BO_TO_DEVICE); }
188
189 private:
190 ::xrt::bo bo;
191 void *ptr;
192 };
193
194 std::unique_ptr<HostMemRegion>
195 allocate(std::size_t size, HostMem::Options opts) const override {
196 return std::unique_ptr<HostMemRegion>(
197 new XrtHostMemRegion(device, size, opts, memoryGroup));
198 }
199
200private:
201 ::xrt::device &device;
202 int32_t memoryGroup;
203};
204} // namespace
205
207 std::string implName,
208 const ServiceImplDetails &details,
209 const HWClientDetails &clients) {
210 if (svcType == typeid(MMIO))
211 return new XrtMMIO(*this, impl->ip, id, clients);
212 else if (svcType == typeid(HostMem))
213 return new XrtHostMem(*this, impl->device, impl->memoryGroup);
214 else if (svcType == typeid(SysInfo))
215 return new MMIOSysInfo(getService<MMIO>());
216 return nullptr;
217}
218
#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:206
Implement the SysInfo API for a standard MMIO protocol.
Definition Services.h:185
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:100
std::string toHex(void *val)
Definition Common.cpp:37
std::vector< HWClientDetail > HWClientDetails
Definition Common.h:99
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:227