// Copyright(c) 2017-2018, Intel Corporation // // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions are met: // // * Redistributions of source code must retain the above copyright notice, // this list of conditions and the following disclaimer. // * 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. // * Neither the name of Intel Corporation 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 OWNER 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 #include #include #include #include #include #include #include #include "pyerrors.h" #include "pyevents.h" #include "pyhandle.h" #include "pyproperties.h" #include "pyshared_buffer.h" #include "pysysobject.h" #include "pytoken.h" namespace py = pybind11; using opae::fpga::types::properties; using opae::fpga::types::token; using opae::fpga::types::handle; using opae::fpga::types::shared_buffer; using opae::fpga::types::event; using opae::fpga::types::error; using opae::fpga::types::sysobject; using opae::fpga::types::version; const char *memory_barrier_doc = R"opaedoc( Place a memory barrier or fence to ensure that all preceding memory operations have completed before continuing. )opaedoc"; #ifdef OPAE_EMBEDDED #include PYBIND11_EMBEDDED_MODULE(_opae, m) { m.def("initialize", &fpgaInitialize); #else PYBIND11_MODULE(_opae, m) { fpgaInitialize(nullptr); #endif py::options opts; // opts.disable_function_signatures(); m.doc() = "Open Programmable Acceleration Engine - Python bindings"; // define enumerations py::enum_(m, "fpga_result", py::arithmetic(), "OPAE return codes") .value("OK", FPGA_OK) .value("INVALID_PARAM", FPGA_INVALID_PARAM) .value("BUSY", FPGA_BUSY) .value("EXCEPTION", FPGA_EXCEPTION) .value("NOT_FOUND", FPGA_NOT_FOUND) .value("NO_MEMORY", FPGA_NO_MEMORY) .value("NOT_SUPPORTED", FPGA_NOT_SUPPORTED) .value("NO_DRIVER", FPGA_NO_DRIVER) .value("NO_DAEMON", FPGA_NO_DAEMON) .value("NO_ACCESS", FPGA_NO_ACCESS) .value("RECONF_ERROR", FPGA_RECONF_ERROR) .export_values(); py::enum_(m, "fpga_objtype", py::arithmetic(), "OPAE resource objects") .value("DEVICE", FPGA_DEVICE) .value("ACCELERATOR", FPGA_ACCELERATOR) .export_values(); py::enum_(m, "fpga_open_flags", py::arithmetic(), "OPAE flags for opening resources") .value("OPEN_SHARED", FPGA_OPEN_SHARED) .export_values(); py::enum_(m, "fpga_event_type", py::arithmetic(), "OPAE event type") .value("EVENT_INTERRUPT", FPGA_EVENT_INTERRUPT) .value("EVENT_ERROR", FPGA_EVENT_ERROR) .value("EVENT_POWER_THERMAL", FPGA_EVENT_POWER_THERMAL) .export_values(); py::enum_(m, "fpga_accelerator_state", py::arithmetic(), "OPAE accelerator_state") .value("ACCELERATOR_ASSIGNED", FPGA_ACCELERATOR_ASSIGNED) .value("ACCELERATOR_UNASSIGNED", FPGA_ACCELERATOR_UNASSIGNED) .export_values(); py::enum_(m, "fpga_sysobject_flags", py::arithmetic(), "OPAE sysobject API flags.") .value("SYSOBJECT_SYNC", FPGA_OBJECT_SYNC) .value("SYSOBJECT_RAW", FPGA_OBJECT_RAW) .value("SYSOBJECT_GLOB", FPGA_OBJECT_GLOB) .value("SYSOBJECT_RECURSE_ONE", FPGA_OBJECT_RECURSE_ONE) .value("SYSOBJECT_RECURSE_ALL", FPGA_OBJECT_RECURSE_ALL) .export_values(); py::enum_( m, "fpga_reconf_flags", py::arithmetic(), "Flags that define how an accelerator is opened.") .value("RECONF_FORCE", FPGA_RECONF_FORCE) .export_values(); // version method m.def("version", &version::as_string, "Get the OPAE runtime version as a string"); m.def("build", &version::build, "Get the OPAE runtime build hash"); // define properties class py::class_ pyproperties(m, "properties", properties_doc()); pyproperties.def(py::init(&properties_get), properties_doc_get()) .def(py::init(&properties_get_token), properties_doc_get_token()) .def(py::init(&properties_get_handle), properties_doc_get_handle()) .def_property("parent", properties_get_parent, properties_set_parent, properties_doc_parent()) .def_property("guid", properties_get_guid, properties_set_guid, properties_doc_guid()) .def_property("type", properties_get_type, properties_set_type, properties_doc_type()) .def_property("segment", properties_get_segment, properties_set_segment, properties_doc_segment()) .def_property("bus", properties_get_bus, properties_set_bus, properties_doc_bus()) .def_property("device", properties_get_device, properties_set_device, properties_doc_device()) .def_property("function", properties_get_function, properties_set_function, properties_doc_function()) .def_property("socket_id", properties_get_socket_id, properties_set_socket_id, properties_doc_socket_id()) .def_property("object_id", properties_get_object_id, properties_set_object_id, properties_doc_object_id()) .def_property("num_errors", properties_get_num_errors, properties_set_num_errors, properties_doc_num_errors()) .def_property("num_slots", properties_get_num_slots, properties_set_num_slots, properties_doc_num_slots()) .def_property("bbs_id", properties_get_bbs_id, properties_set_bbs_id, properties_doc_bbs_id()) .def_property("bbs_version", properties_get_bbs_version, properties_set_bbs_version, properties_doc_bbs_version()) .def_property("vendor_id", properties_get_vendor_id, properties_set_vendor_id, properties_doc_vendor_id()) .def_property("device_id", properties_get_device_id, properties_set_device_id, properties_doc_device_id()) .def_property("model", properties_get_model, properties_set_model, properties_doc_model()) .def_property("local_memory_size", properties_get_local_memory_size, properties_set_local_memory_size, properties_doc_local_memory_size()) .def_property("capabilities", properties_get_capabilities, properties_set_capabilities, properties_doc_capabilities()) .def_property("num_mmio", properties_get_num_mmio, properties_set_num_mmio, properties_doc_num_mmio()) .def_property("num_interrupts", properties_get_num_interrupts, properties_set_num_interrupts, properties_doc_num_interrupts()) .def_property("accelerator_state", properties_get_accelerator_state, properties_set_accelerator_state, properties_doc_accelerator_state()); // memory fence m.def("memory_barrier", []() { std::atomic_thread_fence(std::memory_order_release); }, memory_barrier_doc); // define token class m.def("enumerate", &token::enumerate, token_doc_enumerate()) .def("enumerate", token_enumerate_kwargs, token_doc_enumerate_kwargs()); py::class_ pytoken(m, "token", token_doc()); pytoken.def("__getattr__", token_get_sysobject, sysobject_doc_token_get()) .def("__getitem__", token_get_sysobject, sysobject_doc_token_get()) .def("find", token_find_sysobject, sysobject_doc_token_find(), py::arg("name"), py::arg("flags") = 0); // define handle class m.def("open", handle_open, handle_doc_open(), py::arg("tok"), py::arg("flags") = 0); py::class_ pyhandle(m, "handle"); pyhandle.def("__enter__", handle_context_enter, handle_doc_context_enter()) .def("__exit__", handle_context_exit, handle_doc_context_exit()) .def("reconfigure", handle_reconfigure, handle_doc_reconfigure(), py::arg("slot"), py::arg("fd"), py::arg("flags") = 0) .def("__bool__", handle_valid, handle_doc_valid()) .def("close", &handle::close, handle_doc_close()) .def("reset", &handle::reset, handle_doc_reset()) .def("read_csr32", &handle::read_csr32, handle_doc_read_csr32(), py::arg("offset"), py::arg("csr_space") = 0) .def("read_csr64", &handle::read_csr64, handle_doc_read_csr64(), py::arg("offset"), py::arg("csr_space") = 0) .def("write_csr32", &handle::write_csr32, handle_doc_write_csr32(), py::arg("offset"), py::arg("value"), py::arg("csr_space") = 0) .def("write_csr64", &handle::write_csr64, handle_doc_write_csr64(), py::arg("offset"), py::arg("value"), py::arg("csr_space") = 0) .def("__getattr__", handle_get_sysobject, sysobject_doc_handle_get()) .def("__getitem__", handle_get_sysobject, sysobject_doc_handle_get()) .def("find", handle_find_sysobject, sysobject_doc_handle_find(), py::arg("name"), py::arg("flags") = 0); // define shared_buffer class m.def("allocate_shared_buffer", shared_buffer_allocate, shared_buffer_doc_allocate()); py::class_ pybuffer( m, "shared_buffer", py::buffer_protocol(), shared_buffer_doc()); pybuffer.def("size", &shared_buffer::size, shared_buffer_doc_size()) .def("wsid", &shared_buffer::wsid, shared_buffer_doc_wsid()) .def("io_address", &shared_buffer::io_address, shared_buffer_doc_io_address()) .def("fill", &shared_buffer::fill, shared_buffer_doc_fill()) .def("poll", shared_buffer_poll, "Poll for an 8-bit value being set at given offset", py::arg("offset"), py::arg("value"), py::arg("mask") = 0, py::arg("timeout_usec") = 1000) .def("poll32", shared_buffer_poll, "Poll for a 32-bit value being set at given offset", py::arg("offset"), py::arg("value"), py::arg("mask") = 0, py::arg("timeout_usec") = 1000) .def("poll64", shared_buffer_poll, "Poll for a 64-bit value being set at given offset", py::arg("offset"), py::arg("value"), py::arg("mask"), py::arg("timeout_usec") = 1000) .def("compare", &shared_buffer::compare, shared_buffer_doc_compare()) .def("copy", shared_buffer_copy, shared_buffer_doc_copy(), py::arg("other"), py::arg("size") = 0) .def_buffer([](shared_buffer &b) -> py::buffer_info { return py::buffer_info( const_cast(b.c_type()), sizeof(uint8_t), py::format_descriptor::format(), b.size()); }) .def("read32", &shared_buffer::read, shared_buffer_doc_read32()) .def("read64", &shared_buffer::read, shared_buffer_doc_read64()) .def("write32", &shared_buffer::write, shared_buffer_doc_write32()) .def("write64", &shared_buffer::write, shared_buffer_doc_write64()) .def("split", shared_buffer_split, shared_buffer_doc_split()) .def("__getitem__", shared_buffer_getitem, shared_buffer_doc_getitem()) .def("__setitem__", shared_buffer_setitem, shared_buffer_doc_setitem()) .def("__getitem__", shared_buffer_getslice, shared_buffer_doc_getslice()); // define event class m.def("register_event", event_register_event, event_doc_register_event(), py::arg("handle"), py::arg("event_type"), py::arg("flags") = 0); py::class_ pyevent(m, "event", event_doc()); pyevent.def("os_object", event_os_object, event_doc_os_object()); py::class_ pyerror(m, "error", error_doc()); pyerror.def_property_readonly("name", &error::name, error_doc_name()) .def_property_readonly("can_clear", &error::can_clear, error_doc_can_clear()) .def("read_value", &error::read_value, error_doc_read_value()); m.def("errors", error_errors, error_doc_errors()); // define object class py::class_ pysysobject(m, "sysobject", sysobject_doc()); pysysobject .def("__getattr__", sysobject_get_sysobject, sysobject_doc_object_get()) .def("__getitem__", sysobject_get_sysobject, sysobject_doc_object_get()) .def("find", sysobject_find_sysobject, sysobject_doc_object_find(), py::arg("name"), py::arg("flags") = 0) .def("read64", [](sysobject::ptr_t obj) { return obj->read64(FPGA_OBJECT_SYNC); }) .def("write64", &sysobject::write64) .def("size", &sysobject::size) .def("bytes", sysobject_bytes, sysobject_doc_bytes()) .def("__getitem__", sysobject_getitem, sysobject_doc_getitem()) .def("__getitem__", sysobject_getslice, sysobject_doc_getslice()); }