21 #include <pybind11/pybind11.h>
24 #include <pybind11/stl.h>
33 static const void *
get(
const ChannelPort *port,
const std::type_info *&type) {
47 static const void *
get(
const Service *svc,
const std::type_info *&type) {
48 if (
auto p =
dynamic_cast<const MMIO *
>(svc)) {
52 if (
auto p =
dynamic_cast<const SysInfo *
>(svc)) {
56 if (
auto p =
dynamic_cast<const HostMem *
>(svc)) {
69 struct type_caster<std::any> {
73 static handle
cast(std::any src, return_value_policy ,
75 const std::type_info &t = src.type();
76 if (t ==
typeid(std::string))
77 return py::str(std::any_cast<std::string>(src));
78 else if (t ==
typeid(int64_t))
79 return py::int_(std::any_cast<int64_t>(src));
80 else if (t ==
typeid(uint64_t))
81 return py::int_(std::any_cast<uint64_t>(src));
82 else if (t ==
typeid(
double))
83 return py::float_(std::any_cast<double>(src));
84 else if (t ==
typeid(
bool))
85 return py::bool_(std::any_cast<bool>(src));
86 else if (t ==
typeid(std::nullptr_t))
95 py::object
getPyType(std::optional<const Type *> t) {
96 py::object typesModule = py::module_::import(
"esiaccel.types");
99 return typesModule.attr(
"_get_esi_type")(*t);
104 py::class_<Type>(m,
"Type")
106 .def(
"__repr__", [](
Type &t) {
return "<" + t.
getID() +
">"; });
107 py::class_<ChannelType, Type>(m,
"ChannelType")
109 py::return_value_policy::reference);
110 py::enum_<BundleType::Direction>(m,
"Direction")
111 .value(
"To", BundleType::Direction::To)
112 .value(
"From", BundleType::Direction::From)
114 py::class_<BundleType, Type>(m,
"BundleType")
116 py::return_value_policy::reference);
117 py::class_<VoidType, Type>(m,
"VoidType");
118 py::class_<AnyType, Type>(m,
"AnyType");
119 py::class_<BitVectorType, Type>(m,
"BitVectorType")
121 py::class_<BitsType, BitVectorType>(m,
"BitsType");
122 py::class_<IntegerType, BitVectorType>(m,
"IntegerType");
123 py::class_<SIntType, IntegerType>(m,
"SIntType");
124 py::class_<UIntType, IntegerType>(m,
"UIntType");
125 py::class_<StructType, Type>(m,
"StructType")
127 py::return_value_policy::reference);
128 py::class_<ArrayType, Type>(m,
"ArrayType")
130 py::return_value_policy::reference)
133 py::class_<Constant>(m,
"Constant")
134 .def_property_readonly(
"value", [](
Constant &c) {
return c.
value; })
135 .def_property_readonly(
137 py::return_value_policy::reference);
139 py::class_<AppID>(m,
"AppID")
140 .def(py::init<std::string, std::optional<uint32_t>>(), py::arg(
"name"),
141 py::arg(
"idx") = std::nullopt)
142 .def_property_readonly(
"name", [](
AppID &
id) {
return id.name; })
143 .def_property_readonly(
"idx",
144 [](
AppID &
id) -> py::object {
146 return py::cast(
id.idx);
151 std::string ret =
"<" +
id.name;
153 ret = ret +
"[" + std::to_string(*
id.idx) +
"]";
157 .def(
"__eq__", [](
AppID &a,
AppID &b) {
return a == b; })
158 .def(
"__hash__", [](
AppID &
id) {
160 std::hash<uint32_t>{}(
id.idx.value_or(-1)));
164 py::class_<ModuleInfo>(m,
"ModuleInfo")
165 .def_property_readonly(
"name", [](
ModuleInfo &info) {
return info.
name; })
166 .def_property_readonly(
"summary",
168 .def_property_readonly(
"version",
170 .def_property_readonly(
"repo", [](
ModuleInfo &info) {
return info.
repo; })
171 .def_property_readonly(
"commit_hash",
173 .def_property_readonly(
"constants",
178 std::stringstream os(ret);
183 py::enum_<Logger::Level>(m,
"LogLevel")
189 py::class_<Logger>(m,
"Logger");
191 py::class_<services::Service>(m,
"Service");
193 py::class_<SysInfo, services::Service>(m,
"SysInfo")
197 py::class_<MMIO::RegionDescriptor>(m,
"MMIORegionDescriptor")
198 .def_property_readonly(
"base",
200 .def_property_readonly(
"size",
202 py::class_<services::MMIO, services::Service>(m,
"MMIO")
206 py::return_value_policy::reference);
208 py::class_<services::HostMem::HostMemRegion>(m,
"HostMemRegion")
209 .def_property_readonly(
"ptr",
211 return reinterpret_cast<uintptr_t
>(mem.
getPtr());
213 .def_property_readonly(
"size",
216 py::class_<services::HostMem::Options>(m,
"HostMemOptions")
219 .def_readwrite(
"use_large_pages",
222 std::string ret =
"HostMemOptions(";
226 ret +=
"use_large_pages";
231 py::class_<services::HostMem, services::Service>(m,
"HostMem")
234 py::return_value_policy::take_ownership)
238 return self.mapMemory(
reinterpret_cast<void *
>(ptr), size, opts);
240 py::arg(
"ptr"), py::arg(
"size"),
244 [](
HostMem &
self, uintptr_t ptr) {
245 return self.unmapMemory(
reinterpret_cast<void *
>(ptr));
250 py::class_<std::future<MessageData>>(m,
"MessageDataFuture")
252 [](std::future<MessageData> &f) {
258 .def(
"wait", &std::future<MessageData>::wait)
259 .def(
"get", [](std::future<MessageData> &f) {
261 return py::bytearray((
const char *)data.getBytes(), data.getSize());
264 py::class_<ChannelPort>(m,
"ChannelPort")
266 py::arg(
"buffer_size") = std::nullopt)
269 py::return_value_policy::reference);
271 py::class_<WriteChannelPort, ChannelPort>(m,
"WriteChannelPort")
274 py::buffer_info info(py::buffer(data).request());
275 std::vector<uint8_t> dataVec((uint8_t *)info.ptr,
276 (uint8_t *)info.ptr + info.size);
280 py::buffer_info info(py::buffer(data).request());
281 std::vector<uint8_t> dataVec((uint8_t *)info.ptr,
282 (uint8_t *)info.ptr + info.size);
285 py::class_<ReadChannelPort, ChannelPort>(m,
"ReadChannelPort")
291 return py::bytearray((
const char *)data.getBytes(), data.getSize());
293 "Read data from the channel. Blocking.")
296 py::class_<BundlePort>(m,
"BundlePort")
299 py::return_value_policy::reference)
301 py::return_value_policy::reference)
303 py::return_value_policy::reference);
305 py::class_<ServicePort, BundlePort>(m,
"ServicePort");
307 py::class_<MMIO::MMIORegion, ServicePort>(m,
"MMIORegion")
312 py::class_<FuncService::Function, ServicePort>(m,
"Function")
316 py::bytearray msg) -> std::future<MessageData> {
317 py::buffer_info info(py::buffer(msg).request());
318 std::vector<uint8_t> dataVec((uint8_t *)info.ptr,
319 (uint8_t *)info.ptr + info.size);
321 return self.call(data);
323 py::return_value_policy::take_ownership)
329 py::class_<HWModule>(m,
"HWModule")
332 py::return_value_policy::reference)
334 py::return_value_policy::reference);
337 py::class_<Instance, HWModule>(m,
"Instance")
340 py::class_<Accelerator, HWModule>(m,
"Accelerator");
345 py::return_value_policy::reference);
347 auto accConn = py::class_<AcceleratorConnection>(m,
"AcceleratorConnection");
349 py::class_<Context>(m,
"Context")
353 ctxt.setLogger(std::make_unique<StreamLogger>(level));
362 py::return_value_policy::reference)
368 py::return_value_policy::reference)
370 "get_service_hostmem",
374 py::return_value_policy::reference);
376 py::class_<Manifest>(m,
"Manifest")
377 .def(py::init<Context &, std::string>())
382 auto acc = m.buildAccelerator(conn);
386 py::return_value_policy::reference)
387 .def_property_readonly(
"type_table",
389 std::vector<py::object> ret;
390 std::ranges::transform(m.getTypeTable(),
391 std::back_inserter(ret),
Abstract class representing a connection to an accelerator.
ServiceClass * getService(AppIDPath id={}, std::string implName={}, ServiceImplDetails details={}, HWClientDetails clients={})
Get a typed reference to a particular service type.
AcceleratorServiceThread * getServiceThread()
Return a pointer to the accelerator 'service' thread (or threads).
std::string toStr() const
const Type * getElementType() const
uint64_t getWidth() const
ReadChannelPort & getRawRead(const std::string &name) const
WriteChannelPort & getRawWrite(const std::string &name) const
Get access to the raw byte streams of a channel.
const std::map< std::string, ChannelPort & > & getChannels() const
AppID getID() const
Get the ID of the port.
const ChannelVector & getChannels() const
Unidirectional channels are the basic communication primitive between the host and accelerator.
virtual void disconnect()=0
virtual void connect(std::optional< unsigned > bufferSize=std::nullopt)=0
Set up a connection to the accelerator.
const Type * getType() const
const Type * getInner() const
AcceleratorConnections, Accelerators, and Manifests must all share a context.
std::unique_ptr< AcceleratorConnection > connect(std::string backend, std::string connection)
Connect to an accelerator backend.
const std::map< AppID, Instance * > & getChildren() const
Access the module's children by ID.
const std::vector< services::Service * > & getServices() const
Access the services provided by this module.
std::optional< ModuleInfo > getInfo() const
Access the module's metadata, if any.
const std::map< AppID, const BundlePort & > & getPorts() const
Access the module's ports by ID.
const AppID getID() const
Get the instance's ID, which it will always have.
Class to parse a manifest.
uint32_t getApiVersion() const
std::vector< ModuleInfo > getModuleInfos() const
A logical chunk of data representing serialized data.
A ChannelPort which reads data from the accelerator.
virtual std::future< MessageData > readAsync()
Asynchronous read.
const FieldVector & getFields() const
Root class of the ESI type system.
A ChannelPort which sends data to the accelerator.
virtual void write(const MessageData &)=0
A very basic blocking write API.
virtual bool tryWrite(const MessageData &data)=0
A basic non-blocking write API.
A function call which gets attached to a service port.
virtual std::unique_ptr< HostMemRegion > allocate(std::size_t size, Options opts) const =0
Allocate a region of host memory in accelerator accessible address space.
virtual uint64_t read(uint32_t addr) const
Read a 64-bit value from this region, not the global address space.
virtual void write(uint32_t addr, uint64_t data)
Write a 64-bit value to this region, not the global address space.
virtual RegionDescriptor getDescriptor() const
Get the offset (and size) of the region in the parent (usually global) MMIO address space.
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.
Parent class of all APIs modeled as 'services'.
Information about the Accelerator system.
virtual std::string getJsonManifest() const
Return the JSON-formatted system manifest.
virtual uint32_t getEsiVersion() const =0
Get the ESI version number to check version compatibility.
PYBIND11_MODULE(esiCppAccel, m)
py::object getPyType(std::optional< const Type * > t)
Resolve a Type to the Python wrapper object.
std::unique_ptr< AcceleratorConnection > connect(Context &ctxt, const std::string &backend, const std::string &connection)
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.
std::optional< const Type * > type
std::optional< std::string > version
std::optional< std::string > name
std::map< std::string, Constant > constants
std::optional< std::string > commitHash
std::optional< std::string > repo
std::optional< std::string > summary
RAII memory region for host memory.
virtual void * getPtr() const =0
virtual std::size_t getSize() const =0
Options for allocating host memory.
Describe a region (slice) of MMIO space.
static handle cast(std::any src, return_value_policy, handle)
PYBIND11_TYPE_CASTER(std::any, const_name("object"))
static const void * get(const ChannelPort *port, const std::type_info *&type)
static const void * get(const Service *svc, const std::type_info *&type)