CIRCT 24.0.0git
Loading...
Searching...
No Matches
esiCppAccel.cpp
Go to the documentation of this file.
1//===- esiaccel.cpp - ESI runtime python bindings ---------------*- 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// Simply wrap the C++ API into a Python module called 'esiaccel'.
10//
11//===----------------------------------------------------------------------===//
12
13#include "esi/Accelerator.h"
14#include "esi/Services.h"
15
16#include "esi/backends/Cosim.h"
17
18#include <ranges>
19#include <sstream>
20
21// nanobind includes.
22// Python world does not respect constness. So it doesn't make sense to have
23// const checks. Disable related warnings.
24#if defined(__GNUC__)
25#pragma GCC diagnostic push
26#pragma GCC diagnostic ignored "-Wcast-qual"
27#endif
28#include <nanobind/nanobind.h>
29#include <nanobind/stl/function.h>
30#include <nanobind/stl/map.h>
31#include <nanobind/stl/optional.h>
32#include <nanobind/stl/pair.h>
33#include <nanobind/stl/string.h>
34#include <nanobind/stl/tuple.h>
35#include <nanobind/stl/unique_ptr.h>
36#include <nanobind/stl/vector.h>
37#if defined(__GNUC__)
38#pragma GCC diagnostic pop
39#endif
40
41namespace nb = nanobind;
42
43using namespace esi;
44using namespace esi::services;
45
46namespace nanobind {
47namespace detail {
48
49template <>
50struct type_hook<ChannelPort> {
51 static const std::type_info *get(const ChannelPort *port) {
52 if (dynamic_cast<const WriteChannelPort *>(port))
53 return &typeid(WriteChannelPort);
54 if (dynamic_cast<const ReadChannelPort *>(port))
55 return &typeid(ReadChannelPort);
56 return &typeid(ChannelPort);
57 }
58};
59
60template <>
61struct type_hook<Service> {
62 static const std::type_info *get(const Service *svc) {
63 if (dynamic_cast<const MMIO *>(svc))
64 return &typeid(MMIO);
65 if (dynamic_cast<const SysInfo *>(svc))
66 return &typeid(SysInfo);
67 if (dynamic_cast<const HostMem *>(svc))
68 return &typeid(HostMem);
69 if (dynamic_cast<const TelemetryService *>(svc))
70 return &typeid(TelemetryService);
71 return &typeid(Service);
72 }
73};
74
75/// Nanobind doesn't have a built-in type caster for std::any.
76/// We must provide one which knows about all of the potential types which the
77/// any might be.
78template <>
79struct type_caster<std::any> {
80 NB_TYPE_CASTER(std::any, const_name("object"))
81
82 static handle from_cpp(const std::any &src, rv_policy /* policy */,
83 cleanup_list * /* cleanup */) {
84 const std::type_info &t = src.type();
85 if (t == typeid(std::string))
86 return nb::str(std::any_cast<std::string>(src).c_str()).release();
87 else if (t == typeid(int64_t))
88 return nb::int_(std::any_cast<int64_t>(src)).release();
89 else if (t == typeid(uint64_t))
90 return nb::int_(std::any_cast<uint64_t>(src)).release();
91 else if (t == typeid(double))
92 return nb::float_(std::any_cast<double>(src)).release();
93 else if (t == typeid(bool))
94 return nb::bool_(std::any_cast<bool>(src)).release();
95 else if (t == typeid(std::nullptr_t))
96 return nb::none().release();
97 return nb::none().release();
98 }
99};
100} // namespace detail
101} // namespace nanobind
102
103/// Resolve a Type to the Python wrapper object.
104nb::object getPyType(std::optional<const Type *> t) {
105 nb::object typesModule = nb::module_::import_("esiaccel.types");
106 if (!t)
107 return nb::none();
108 return typesModule.attr("_get_esi_type")(*t);
109}
110
111// NOLINTNEXTLINE(readability-identifier-naming)
112NB_MODULE(esiCppAccel, m) {
113 // TODO: Fix leaks! The one I know of is in the callback code -- if one
114 // registers a python callback it creates a leak.
115 nb::set_leak_warnings(false);
116
117 nb::class_<Type>(m, "Type")
118 .def(nb::init<const Type::ID &>(), nb::arg("id"))
119 .def_prop_ro("id", &Type::getID)
120 .def_prop_ro("bit_width", &Type::getBitWidth)
121 .def("__repr__", [](Type &t) { return "<" + t.getID() + ">"; });
122 nb::class_<ChannelType, Type>(m, "ChannelType")
123 .def(nb::init<const Type::ID &, const Type *>(), nb::arg("id"),
124 nb::arg("inner"))
125 .def_prop_ro("inner", &ChannelType::getInner, nb::rv_policy::reference);
126 nb::enum_<BundleType::Direction>(m, "Direction")
127 .value("To", BundleType::Direction::To)
128 .value("From", BundleType::Direction::From)
129 .export_values();
130 nb::class_<BundleType, Type>(m, "BundleType")
131 .def(nb::init<const Type::ID &, const BundleType::ChannelVector &>(),
132 nb::arg("id"), nb::arg("channels"))
133 .def_prop_ro("channels", &BundleType::getChannels,
134 nb::rv_policy::reference);
135 nb::class_<VoidType, Type>(m, "VoidType")
136 .def(nb::init<const Type::ID &>(), nb::arg("id"));
137 nb::class_<AnyType, Type>(m, "AnyType")
138 .def(nb::init<const Type::ID &>(), nb::arg("id"));
139 nb::class_<TypeAliasType, Type>(m, "TypeAliasType")
140 .def(nb::init<const Type::ID &, std::string, const Type *>(),
141 nb::arg("id"), nb::arg("name"), nb::arg("inner_type"))
142 .def_prop_ro("name", &TypeAliasType::getName)
143 .def_prop_ro("inner", &TypeAliasType::getInnerType,
144 nb::rv_policy::reference);
145 nb::class_<BitVectorType, Type>(m, "BitVectorType")
146 .def(nb::init<const Type::ID &, uint64_t>(), nb::arg("id"),
147 nb::arg("width"))
148 .def_prop_ro("width", &BitVectorType::getWidth);
149 nb::class_<BitsType, BitVectorType>(m, "BitsType")
150 .def(nb::init<const Type::ID &, uint64_t>(), nb::arg("id"),
151 nb::arg("width"));
152 nb::class_<IntegerType, BitVectorType>(m, "IntegerType")
153 .def(nb::init<const Type::ID &, uint64_t>(), nb::arg("id"),
154 nb::arg("width"));
155 nb::class_<SIntType, IntegerType>(m, "SIntType")
156 .def(nb::init<const Type::ID &, uint64_t>(), nb::arg("id"),
157 nb::arg("width"));
158 nb::class_<UIntType, IntegerType>(m, "UIntType")
159 .def(nb::init<const Type::ID &, uint64_t>(), nb::arg("id"),
160 nb::arg("width"));
161 nb::class_<StructType, Type>(m, "StructType")
162 .def(nb::init<const Type::ID &, const StructType::FieldVector &, bool>(),
163 nb::arg("id"), nb::arg("fields"), nb::arg("reverse") = true)
164 .def_prop_ro("fields", &StructType::getFields, nb::rv_policy::reference)
165 .def_prop_ro("reverse", &StructType::isReverse);
166 nb::class_<ArrayType, Type>(m, "ArrayType")
167 .def(nb::init<const Type::ID &, const Type *, uint64_t>(), nb::arg("id"),
168 nb::arg("element_type"), nb::arg("size"))
169 .def_prop_ro("element", &ArrayType::getElementType,
170 nb::rv_policy::reference)
171 .def_prop_ro("size", &ArrayType::getSize);
172 nb::class_<WindowType::Field>(m, "WindowField")
173 .def(nb::init<>())
174 .def(nb::init<std::string, uint64_t, uint64_t>(), nb::arg("name"),
175 nb::arg("num_items") = 0, nb::arg("bulk_count_width") = 0)
176 .def_rw("name", &WindowType::Field::name)
177 .def_rw("num_items", &WindowType::Field::numItems)
178 .def_rw("bulk_count_width", &WindowType::Field::bulkCountWidth);
179 nb::class_<WindowType::Frame>(m, "WindowFrame")
180 .def(nb::init<>())
181 .def(nb::init<std::string, const std::vector<WindowType::Field> &>(),
182 nb::arg("name"), nb::arg("fields"))
183 .def_rw("name", &WindowType::Frame::name)
184 .def_rw("fields", &WindowType::Frame::fields);
185 nb::class_<WindowType, Type>(m, "WindowType")
186 .def(nb::init<const Type::ID &, const std::string &, const Type *,
187 const Type *, const std::vector<WindowType::Frame> &>(),
188 nb::arg("id"), nb::arg("name"), nb::arg("into_type"),
189 nb::arg("lowered_type"), nb::arg("frames"))
190 .def_prop_ro("name", &WindowType::getName)
191 .def_prop_ro("into", &WindowType::getIntoType, nb::rv_policy::reference)
192 .def_prop_ro("lowered", &WindowType::getLoweredType,
193 nb::rv_policy::reference)
194 .def_prop_ro("frames", &WindowType::getFrames, nb::rv_policy::reference);
195 nb::class_<ListType, Type>(m, "ListType")
196 .def(nb::init<const Type::ID &, const Type *>(), nb::arg("id"),
197 nb::arg("element_type"))
198 .def_prop_ro("element", &ListType::getElementType,
199 nb::rv_policy::reference);
200 nb::class_<UnionType, Type>(m, "UnionType")
201 .def(nb::init<const Type::ID &, const UnionType::FieldVector &>(),
202 nb::arg("id"), nb::arg("fields"))
203 .def_prop_ro("fields", &UnionType::getFields, nb::rv_policy::reference);
204
205 nb::class_<Constant>(m, "Constant")
206 .def_prop_ro("value", [](Constant &c) { return c.value; })
207 .def_prop_ro("type", [](Constant &c) { return getPyType(*c.type); });
208
209 nb::class_<AppID>(m, "AppID")
210 .def(nb::init<std::string, std::optional<uint32_t>>(), nb::arg("name"),
211 nb::arg("idx") = std::nullopt)
212 .def_prop_ro("name", [](AppID &id) { return id.name; })
213 .def_prop_ro("idx",
214 [](AppID &id) -> nb::object {
215 if (id.idx)
216 return nb::cast(id.idx);
217 return nb::none();
218 })
219 .def("__repr__",
220 [](AppID &id) {
221 std::string ret = "<" + id.name;
222 if (id.idx)
223 ret = ret + "[" + std::to_string(*id.idx) + "]";
224 ret = ret + ">";
225 return ret;
226 })
227 .def("__eq__", [](AppID &a, AppID &b) { return a == b; })
228 .def("__hash__", [](AppID &id) {
229 return utils::hash_combine(std::hash<std::string>{}(id.name),
230 std::hash<uint32_t>{}(id.idx.value_or(-1)));
231 });
232 nb::class_<AppIDPath>(m, "AppIDPath").def("__repr__", &AppIDPath::toStr);
233
234 nb::class_<ModuleInfo>(m, "ModuleInfo")
235 .def_prop_ro("name", [](ModuleInfo &info) { return info.name; })
236 .def_prop_ro("summary", [](ModuleInfo &info) { return info.summary; })
237 .def_prop_ro("version", [](ModuleInfo &info) { return info.version; })
238 .def_prop_ro("repo", [](ModuleInfo &info) { return info.repo; })
239 .def_prop_ro("commit_hash",
240 [](ModuleInfo &info) { return info.commitHash; })
241 .def_prop_ro("constants", [](ModuleInfo &info) { return info.constants; })
242 // TODO: "extra" field.
243 .def("__repr__", [](ModuleInfo &info) {
244 std::string ret;
245 std::stringstream os(ret);
246 os << info;
247 return os.str();
248 });
249
250 nb::enum_<Logger::Level>(m, "LogLevel")
251 .value("Debug", Logger::Level::Debug)
252 .value("Info", Logger::Level::Info)
253 .value("Warning", Logger::Level::Warning)
254 .value("Error", Logger::Level::Error)
255 .export_values();
256 nb::class_<Logger>(m, "Logger");
257
258 nb::class_<services::Service>(m, "Service")
259 .def("get_service_symbol", &services::Service::getServiceSymbol);
260
261 nb::class_<SysInfo, services::Service>(m, "SysInfo")
262 .def("esi_version", &SysInfo::getEsiVersion)
263 .def("json_manifest", &SysInfo::getJsonManifest)
264 .def("cycle_count", &SysInfo::getCycleCount,
265 "Get the current cycle count of the accelerator system")
266 .def("core_clock_frequency", &SysInfo::getCoreClockFrequency,
267 "Get the core clock frequency of the accelerator system in Hz");
268
269 nb::class_<MMIO::RegionDescriptor>(m, "MMIORegionDescriptor")
270 .def_prop_ro("base", [](MMIO::RegionDescriptor &r) { return r.base; })
271 .def_prop_ro("size", [](MMIO::RegionDescriptor &r) { return r.size; });
272 nb::class_<services::MMIO, services::Service>(m, "MMIO")
273 // These can block (e.g. on cosim backpressure); yield the GIL meanwhile.
274 .def("read", &services::MMIO::read,
275 nb::call_guard<nb::gil_scoped_release>())
276 .def("write", &services::MMIO::write,
277 nb::call_guard<nb::gil_scoped_release>())
278 .def_prop_ro("regions", &services::MMIO::getRegions,
279 nb::rv_policy::reference);
280
281 nb::class_<services::HostMem::HostMemRegion>(m, "HostMemRegion")
282 .def_prop_ro("ptr",
284 return reinterpret_cast<uintptr_t>(mem.getPtr());
285 })
286 .def_prop_ro("size", &services::HostMem::HostMemRegion::getSize);
287
288 nb::class_<services::HostMem::Options>(m, "HostMemOptions")
289 .def(nb::init<>())
290 .def_rw("writeable", &services::HostMem::Options::writeable)
291 .def_rw("use_large_pages", &services::HostMem::Options::useLargePages)
292 .def("__repr__", [](services::HostMem::Options &opts) {
293 std::string ret = "HostMemOptions(";
294 if (opts.writeable)
295 ret += "writeable ";
296 if (opts.useLargePages)
297 ret += "use_large_pages";
298 ret += ")";
299 return ret;
300 });
301
302 nb::class_<services::HostMem, services::Service>(m, "HostMem")
303 .def("start", &services::HostMem::start,
304 "Enable the host memory service (e.g. start servicing the "
305 "accelerator's read and write requests). Required before the "
306 "accelerator accesses host memory on some backends.")
307 .def("allocate", &services::HostMem::allocate, nb::arg("size"),
308 nb::arg("options") = services::HostMem::Options(),
309 nb::rv_policy::take_ownership)
310 .def(
311 "map_memory",
312 [](HostMem &self, uintptr_t ptr, size_t size, HostMem::Options opts) {
313 return self.mapMemory(reinterpret_cast<void *>(ptr), size, opts);
314 },
315 nb::arg("ptr"), nb::arg("size"),
316 nb::arg("options") = services::HostMem::Options())
317 .def(
318 "unmap_memory",
319 [](HostMem &self, uintptr_t ptr) {
320 return self.unmapMemory(reinterpret_cast<void *>(ptr));
321 },
322 nb::arg("ptr"));
323 nb::class_<services::TelemetryService, services::Service>(m,
324 "TelemetryService");
325
326 nb::class_<std::future<MessageData>>(m, "MessageDataFuture")
327 .def("valid", [](std::future<MessageData> &f) { return f.valid(); })
328 .def("wait",
329 [](std::future<MessageData> &f) {
330 // Yield the GIL while waiting for the future to complete, in case
331 // of python callbacks occurring from other threads while waiting.
332 nb::gil_scoped_release release{};
333 f.wait();
334 })
335 .def("get", [](std::future<MessageData> &f) {
336 std::optional<MessageData> data;
337 {
338 // Yield the GIL while waiting for the future to complete, in case of
339 // python callbacks occurring from other threads while waiting.
340 nb::gil_scoped_release release{};
341 data.emplace(f.get());
342 }
343 return nb::bytearray((const char *)data->getBytes(), data->getSize());
344 });
345
346 nb::class_<ChannelPort::ConnectOptions>(m, "ConnectOptions")
347 .def(nb::init<>())
348 .def_rw("buffer_size", &ChannelPort::ConnectOptions::bufferSize,
349 nb::arg("buffer_size").none())
350 .def_rw("translate_message",
352
353 nb::class_<ChannelPort>(m, "ChannelPort")
354 .def("connect", &ChannelPort::connect, nb::arg("options"),
355 "Connect with specified options")
356 .def("disconnect", &ChannelPort::disconnect)
357 .def_prop_ro("type", &ChannelPort::getType, nb::rv_policy::reference)
358 .def_prop_ro("windowType", &ChannelPort::getWindowType,
359 nb::rv_policy::reference);
360
361 nb::class_<WriteChannelPort, ChannelPort>(m, "WriteChannelPort")
362 .def("write",
363 [](WriteChannelPort &p, nb::bytearray data) {
364 std::vector<uint8_t> dataVec((const uint8_t *)data.c_str(),
365 (const uint8_t *)data.c_str() +
366 data.size());
367 // Blocks under backpressure. Yield the GIL so python callbacks
368 // on other threads can make progress meanwhile.
369 nb::gil_scoped_release release{};
370 p.write(dataVec);
371 })
372 .def("tryWrite", [](WriteChannelPort &p, nb::bytearray data) {
373 std::vector<uint8_t> dataVec((const uint8_t *)data.c_str(),
374 (const uint8_t *)data.c_str() +
375 data.size());
376 return p.tryWrite(dataVec);
377 });
378 nb::class_<ReadChannelPort, ChannelPort>(m, "ReadChannelPort")
379 .def(
380 "read",
381 [](ReadChannelPort &p) -> nb::bytearray {
382 MessageData data;
383 p.read(data);
384 return nb::bytearray((const char *)data.getBytes(), data.getSize());
385 },
386 "Read data from the channel. Blocking.")
387 .def("read_async", &ReadChannelPort::readAsync);
388
389 nb::class_<BundlePort>(m, "BundlePort")
390 .def_prop_ro("id", &BundlePort::getID)
391 .def_prop_ro("channels", &BundlePort::getChannels,
392 nb::rv_policy::reference)
393 .def("getWrite", &BundlePort::getRawWrite, nb::rv_policy::reference)
394 .def("getRead", &BundlePort::getRawRead, nb::rv_policy::reference);
395
396 nb::class_<ServicePort, BundlePort>(m, "ServicePort");
397
398 nb::class_<MMIO::MMIORegion, ServicePort>(m, "MMIORegion")
399 .def_prop_ro("descriptor", &MMIO::MMIORegion::getDescriptor)
400 // These can block (e.g. on cosim backpressure); yield the GIL meanwhile.
401 .def("read", &MMIO::MMIORegion::read,
402 nb::call_guard<nb::gil_scoped_release>())
403 .def("write", &MMIO::MMIORegion::write,
404 nb::call_guard<nb::gil_scoped_release>());
405
406 nb::class_<FuncService::Function, ServicePort>(m, "Function")
407 .def("call",
408 [](FuncService::Function &self,
409 nb::bytearray msg) -> std::future<MessageData> {
410 std::vector<uint8_t> dataVec((const uint8_t *)msg.c_str(),
411 (const uint8_t *)msg.c_str() +
412 msg.size());
413 MessageData data(dataVec);
414 // Sending the argument can block on backpressure.
415 nb::gil_scoped_release release{};
416 return self.call(data);
417 })
418 .def("connect", [](FuncService::Function &self) { self.connect(); });
419
420 nb::class_<CallService::Callback, ServicePort>(m, "Callback")
421 .def("connect", [](CallService::Callback &self,
422 std::function<nb::object(nb::object)> pyCallback) {
423 // TODO: Under certain conditions this will cause python to crash. I
424 // don't remember how to replicate these crashes, but IIRC they are
425 // deterministic.
426 self.connect([pyCallback](const MessageData &req) -> MessageData {
427 nb::gil_scoped_acquire acquire{};
428 std::vector<uint8_t> arg(req.getBytes(),
429 req.getBytes() + req.getSize());
430 nb::bytes argObj((const char *)arg.data(), arg.size());
431 auto ret = pyCallback(argObj);
432 if (ret.is_none())
433 return MessageData();
434 nb::bytearray retBytes = nb::cast<nb::bytearray>(ret);
435 std::vector<uint8_t> dataVec((const uint8_t *)retBytes.c_str(),
436 (const uint8_t *)retBytes.c_str() +
437 retBytes.size());
438 return MessageData(dataVec);
439 });
440 });
441
442 nb::class_<TelemetryService::Metric, ServicePort>(m, "Metric")
443 .def("connect", &TelemetryService::Metric::connect)
444 .def("read", &TelemetryService::Metric::read)
445 .def("readInt", &TelemetryService::Metric::readInt);
446
447 nb::class_<ChannelService::ToHost, ServicePort>(m, "ToHostChannel")
448 .def("connect", &ChannelService::ToHost::connect)
449 .def("read", &ChannelService::ToHost::read);
450
451 nb::class_<ChannelService::FromHost, ServicePort>(m, "FromHostChannel")
452 .def("connect", &ChannelService::FromHost::connect)
453 .def(
454 "write",
455 [](ChannelService::FromHost &self, nb::bytearray data) {
456 std::vector<uint8_t> dataVec((const uint8_t *)data.c_str(),
457 (const uint8_t *)data.c_str() +
458 data.size());
459 // Blocks under backpressure; yield the GIL meanwhile.
460 nb::gil_scoped_release release{};
461 self.write(MessageData(dataVec));
462 },
463 nb::arg("data"));
464
465 // Store this variable (not commonly done) as the "children" method needs for
466 // "Instance" to be defined first.
467 auto hwmodule =
468 nb::class_<HWModule>(m, "HWModule")
469 .def_prop_ro("info", &HWModule::getInfo)
470 .def_prop_ro("ports", &HWModule::getPorts, nb::rv_policy::reference)
471 .def_prop_ro("services", &HWModule::getServices,
472 nb::rv_policy::reference);
473
474 // In order to inherit methods from "HWModule", it needs to be defined first.
475 nb::class_<Instance, HWModule>(m, "Instance")
476 .def_prop_ro("id", &Instance::getID);
477
478 nb::class_<Accelerator, HWModule>(m, "Accelerator");
479
480 // Since this returns a vector of Instance*, we need to define Instance first
481 // or else stubgen complains.
482 hwmodule.def_prop_ro("children", &HWModule::getChildren,
483 nb::rv_policy::reference);
484
485 auto accConn = nb::class_<AcceleratorConnection>(m, "AcceleratorConnection");
486
487 nb::class_<Context>(
488 m, "Context",
489 "An ESI context owns everything -- types, accelerator connections, and "
490 "the accelerator facade (aka Accelerator) itself. It MUST NOT be garbage "
491 "collected while the accelerator is still in use. When it is destroyed, "
492 "all accelerator connections are disconnected.")
493 .def(nb::init<>(), "Create a context with a default logger.")
494 .def("connect", &Context::connect, nb::rv_policy::reference)
495 .def("set_stdio_logger", [](Context &ctxt, Logger::Level level) {
496 ctxt.setLogger(std::make_unique<StreamLogger>(level));
497 });
498
499 accConn
500 .def(
501 "sysinfo",
502 [](AcceleratorConnection &acc) {
503 return acc.getService<services::SysInfo>({});
504 },
505 nb::rv_policy::reference)
506 .def(
507 "get_service_mmio",
508 [](AcceleratorConnection &acc) {
509 return acc.getService<services::MMIO>({});
510 },
511 nb::rv_policy::reference)
512 .def(
513 "get_service_hostmem",
514 [](AcceleratorConnection &acc) {
515 return acc.getService<services::HostMem>({});
516 },
517 nb::rv_policy::reference)
518 .def("get_accelerator", &AcceleratorConnection::getAccelerator,
519 nb::rv_policy::reference);
520
521 nb::class_<Manifest>(m, "Manifest")
522 .def(nb::init<Context &, std::string>())
523 .def_prop_ro("api_version", &Manifest::getApiVersion)
524 .def(
525 "build_accelerator",
526 [&](Manifest &m, AcceleratorConnection &conn) -> Accelerator * {
527 auto *acc = m.buildAccelerator(conn);
528 conn.getServiceThread()->addPoll(*acc);
529 return acc;
530 },
531 nb::rv_policy::reference)
532 .def_prop_ro("type_table",
533 [](Manifest &m) {
534 std::vector<nb::object> ret;
535 std::ranges::transform(m.getTypeTable(),
536 std::back_inserter(ret), getPyType);
537 return ret;
538 })
539 .def_prop_ro("module_infos", &Manifest::getModuleInfos);
540}
Abstract class representing a connection to an accelerator.
Accelerator & getAccelerator()
Top level accelerator class.
Definition Accelerator.h:85
std::string toStr() const
Definition Manifest.cpp:816
const Type * getElementType() const
Definition Types.h:308
uint64_t getSize() const
Definition Types.h:309
uint64_t getWidth() const
Definition Types.h:215
ReadChannelPort & getRawRead(const std::string &name) const
Definition Ports.cpp:52
WriteChannelPort & getRawWrite(const std::string &name) const
Get access to the raw byte streams of a channel.
Definition Ports.cpp:42
const PortMap & getChannels() const
Definition Ports.h:658
AppID getID() const
Get the ID of the port.
Definition Ports.h:650
const ChannelVector & getChannels() const
Definition Types.h:114
Unidirectional channels are the basic communication primitive between the host and accelerator.
Definition Ports.h:115
const Type * getType() const
Definition Ports.h:219
virtual void connect(const ConnectOptions &options=ConnectOptions())=0
Set up a connection to the accelerator.
virtual void disconnect()=0
const WindowType * getWindowType() const
If this port carries a windowed type, return the original WindowType (whose intoType is what getType(...
Definition Ports.h:224
const Type * getInner() const
Definition Types.h:129
AcceleratorConnections, Accelerators, and Manifests must all share a context.
Definition Context.h:34
AcceleratorConnection * connect(std::string backend, std::string connection)
Connect to an accelerator backend.
void setLogger(std::unique_ptr< Logger > logger)
Register a logger with the accelerator. Assumes ownership of the logger.
Definition Context.h:64
const std::map< AppID, BundlePort & > & getPorts() const
Access the module's ports by ID.
Definition Design.h:80
const std::map< AppID, Instance * > & getChildren() const
Access the module's children by ID.
Definition Design.h:71
const std::vector< services::Service * > & getServices() const
Access the services provided by this module.
Definition Design.h:82
std::optional< ModuleInfo > getInfo() const
Access the module's metadata, if any.
Definition Design.h:62
AppID getID() const
Get the instance's ID, which it will always have.
Definition Design.h:124
const Type * getElementType() const
Definition Types.h:410
Class to parse a manifest.
Definition Manifest.h:39
uint32_t getApiVersion() const
std::vector< ModuleInfo > getModuleInfos() const
A concrete flat message backed by a single vector of bytes.
Definition Common.h:197
const uint8_t * getBytes() const
Definition Common.h:208
size_t getSize() const
Get the size of the data in bytes.
Definition Common.h:222
A ChannelPort which reads data from the accelerator.
Definition Ports.h:479
virtual std::future< MessageData > readAsync()
Asynchronous polling read.
Definition Ports.cpp:225
bool isReverse() const
Definition Types.h:293
const FieldVector & getFields() const
Definition Types.h:272
const Type * getInnerType() const
Definition Types.h:177
const std::string & getName() const
Definition Types.h:176
Root class of the ESI type system.
Definition Types.h:36
virtual std::ptrdiff_t getBitWidth() const
Definition Types.h:43
std::string ID
Definition Types.h:38
ID getID() const
Definition Types.h:42
const FieldVector & getFields() const
Definition Types.h:383
const std::vector< Frame > & getFrames() const
Definition Types.h:358
const Type * getLoweredType() const
Definition Types.h:357
const std::string & getName() const
Definition Types.h:355
const Type * getIntoType() const
Definition Types.h:356
A ChannelPort which sends data to the accelerator.
Definition Ports.h:308
void write(const MessageData &data)
A very basic blocking write API.
Definition Ports.h:327
bool tryWrite(const MessageData &data)
A basic non-blocking write API.
Definition Ports.h:358
A function call which gets attached to a service port.
Definition Services.h:437
A port which writes data to the accelerator (from_host).
Definition Services.h:347
std::future< MessageData > read()
Definition Services.cpp:261
A function call which gets attached to a service port.
Definition Services.h:385
virtual void start()
In cases where necessary, enable host memory services.
Definition Services.h:292
services::HostMemRegion HostMemRegion
RAII memory region for host memory. See services::HostMemRegion.
Definition Services.h:289
virtual void unmapMemory(void *ptr) const
Unmap memory which was previously mapped with 'mapMemory'.
Definition Services.h:309
virtual std::unique_ptr< HostMemRegion > allocate(std::size_t size, Options opts) const override=0
Allocate a region of host memory in accelerator accessible address space.
virtual bool mapMemory(void *ptr, std::size_t size, Options opts) const
Try to make a region of host memory accessible to the accelerator.
Definition Services.h:304
virtual uint64_t read(uint32_t addr) const
Read a 64-bit value from this region, not the global address space.
Definition Services.cpp:132
virtual void write(uint32_t addr, uint64_t data)
Write a 64-bit value to this region, not the global address space.
Definition Services.cpp:137
virtual RegionDescriptor getDescriptor() const
Get the offset (and size) of the region in the parent (usually global) MMIO address space.
Definition Services.h:194
virtual uint64_t read(uint32_t addr) const =0
Read a 64-bit value from the global MMIO space.
virtual void write(uint32_t addr, uint64_t data)=0
Write a 64-bit value to the global MMIO space.
const std::map< AppIDPath, RegionDescriptor > & getRegions() const
Get the regions of MMIO space that this service manages.
Definition Services.h:158
Parent class of all APIs modeled as 'services'.
Definition Services.h:59
virtual std::string getServiceSymbol() const =0
Information about the Accelerator system.
Definition Services.h:113
virtual std::optional< uint64_t > getCoreClockFrequency() const
Get the "core" clock frequency of the accelerator system in Hz.
Definition Services.h:127
virtual std::string getJsonManifest() const
Return the JSON-formatted system manifest.
Definition Services.cpp:40
virtual uint32_t getEsiVersion() const =0
Get the ESI version number to check version compatibility.
virtual std::optional< uint64_t > getCycleCount() const
Get the current cycle count of the accelerator system.
Definition Services.h:124
void connect()
Connect to a particular telemetry port. Offset should be non-nullopt.
Definition Services.cpp:481
std::future< MessageData > read()
Definition Services.cpp:488
Service for retrieving telemetry data from the accelerator.
Definition Services.h:485
nb::object getPyType(std::optional< const Type * > t)
Resolve a Type to the Python wrapper object.
NB_MODULE(esiCppAccel, m)
size_t hash_combine(size_t h1, size_t h2)
C++'s stdlib doesn't have a hash_combine function. This is a simple one.
Definition Utils.h:36
Definition esi.py:1
std::optional< unsigned > bufferSize
The buffer size is optional and should be considered merely a hint.
Definition Ports.h:124
bool translateMessage
If the type of this port is a window, translate the incoming/outgoing data into its underlying ('into...
Definition Ports.h:183
std::any value
Definition Common.h:69
std::optional< const Type * > type
Definition Common.h:70
uint64_t bulkCountWidth
Definition Types.h:340
std::string name
Definition Types.h:338
std::vector< Field > fields
Definition Types.h:347
std::string name
Definition Types.h:346
Options for allocating host memory.
Definition Services.h:268
virtual std::size_t getSize() const =0
virtual void * getPtr() const =0
Get a pointer to the host memory.
Describe a region (slice) of MMIO space.
Definition Services.h:143
static handle from_cpp(const std::any &src, rv_policy, cleanup_list *)
static const std::type_info * get(const ChannelPort *port)
static const std::type_info * get(const Service *svc)