summaryrefslogtreecommitdiff
path: root/python/openvino/runtime/coredla_device/src/mmd_wrapper.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'python/openvino/runtime/coredla_device/src/mmd_wrapper.cpp')
-rw-r--r--python/openvino/runtime/coredla_device/src/mmd_wrapper.cpp172
1 files changed, 172 insertions, 0 deletions
diff --git a/python/openvino/runtime/coredla_device/src/mmd_wrapper.cpp b/python/openvino/runtime/coredla_device/src/mmd_wrapper.cpp
new file mode 100644
index 0000000..bbb052a
--- /dev/null
+++ b/python/openvino/runtime/coredla_device/src/mmd_wrapper.cpp
@@ -0,0 +1,172 @@
+// Copyright 2020-2023 Intel Corporation.
+//
+// This software and the related documents are Intel copyrighted materials,
+// and your use of them is governed by the express license under which they
+// were provided to you ("License"). Unless the License provides otherwise,
+// you may not use, modify, copy, publish, distribute, disclose or transmit
+// this software or the related documents without Intel's prior written
+// permission.
+//
+// This software and the related documents are provided as is, with no express
+// or implied warranties, other than those that are expressly stated in the
+// License.
+
+#include "mmd_wrapper.h"
+#include "aocl_mmd.h" // aocl_mmd_***
+#include "dla_dma_constants.h" // DLA_DMA_CSR_OFFSET_***
+
+#include <cassert> // assert
+#include <cstddef> // size_t
+#include <iostream> // std::cerr
+#include <stdexcept> // std::runtime_error
+#include <string> // std::string
+
+// All board variants must obey the CoreDLA CSR spec, which says that all access must be
+// - 32 bits in size
+// - address must be 4 byte aligned
+// - within the address range, CSR size is 2048 bytes
+constexpr uint64_t DLA_CSR_ALIGNMENT = 4;
+constexpr uint64_t DLA_CSR_SIZE = 2048;
+
+// assert(status == 0) is removed by the c++ processor when compiling in release mode
+// this is a handy workaround for suppressing the compiler warning about an unused variable
+template <class T>
+void suppress_warning_unused_varible(const T &) {}
+
+MmdWrapper::MmdWrapper() {
+ // Open the MMD
+ constexpr size_t MAX_BOARD_NAMES_LEN = 4096;
+ char name[MAX_BOARD_NAMES_LEN];
+ size_t sz;
+ int status = aocl_mmd_get_offline_info(AOCL_MMD_BOARD_NAMES, MAX_BOARD_NAMES_LEN, name, &sz);
+ if (status) {
+ std::string msg = "Failed to query a board name from MMD. Perhaps no FPGA device is available?";
+ throw std::runtime_error(msg);
+ }
+ int handle = aocl_mmd_open(name);
+ if (handle < 0) {
+ std::string msg = "Failed to open MMD";
+ throw std::runtime_error(msg);
+ }
+ handle_ = handle;
+
+ // Query some board-specific information from the MMD. Some values can be hardcoded constants
+ // where different boards have different constants, e.g. capacity of FPGA DDR. Others values may
+ // be determined experimentally e.g. start and stop a counter with a known duration in between to
+ // measure the clk_dla frequency.
+ maxInstances_ = dla_mmd_get_max_num_instances();
+ ddrSizePerInstance_ = dla_mmd_get_ddr_size_per_instance();
+ coreDlaClockFreq_ = dla_mmd_get_coredla_clock_freq(handle_);
+
+ // On DE10 Agilex boards with GCC 8.3.0, we noticed that the clock frequency was being read as 0,
+ // around 50% of the time, and around 10% of the time on GCC 9.2.0, causing failures on perf_est
+ // tests. This retry loop will recall the function until the coreDlaClockFreq is non zero, or
+ // it exhausts 10 retries.
+ // We have no idea why this happens currently, but it typically passes by the second try.
+ int clockFreqRetries = 10;
+ while (coreDlaClockFreq_ == 0 && clockFreqRetries > 0) {
+ coreDlaClockFreq_ = dla_mmd_get_coredla_clock_freq(handle_);
+ clockFreqRetries--;
+ }
+ ddrClockFreq_ = dla_mmd_get_ddr_clock_freq();
+}
+
+MmdWrapper::~MmdWrapper() {
+ // Close the MMD
+ int status = aocl_mmd_close(handle_);
+ if (status) {
+ // Avoid throwning an exception from a Destructor. We are ultimately
+ // part of a (virtual) OpenVINO destructor, so we should follow the
+ // noexcept(true) that it advertises. Perhaps we can close the mmd
+ // as a separate step prior to destruction to make signaling errors
+ // easier?
+ std::cerr << "Failed to close MMD" << std::endl;
+ std::cerr << "Error status " << status << std::endl;
+ std::exit(1);
+ }
+}
+
+void MmdWrapper::RegisterISR(interrupt_service_routine_signature func, void *data) const {
+ // register an interrupt handler
+ int status = aocl_mmd_set_interrupt_handler(handle_, func, data);
+ if (status) {
+ std::string msg = "Failed to register an interrupt handler with MMD";
+ throw std::runtime_error(msg);
+ }
+}
+
+void MmdWrapper::WriteToCsr(int instance, uint32_t addr, uint32_t data) const {
+ assert(instance >= 0 && instance < maxInstances_);
+ assert(addr + sizeof(uint32_t) <= DLA_CSR_SIZE);
+ assert(addr % DLA_CSR_ALIGNMENT == 0);
+ int status = dla_mmd_csr_write(handle_, instance, addr, &data);
+ assert(status == 0);
+ suppress_warning_unused_varible(status);
+}
+
+uint32_t MmdWrapper::ReadFromCsr(int instance, uint32_t addr) const {
+ assert(instance >= 0 && instance < maxInstances_);
+ assert(addr + sizeof(uint32_t) <= DLA_CSR_SIZE);
+ assert(addr % DLA_CSR_ALIGNMENT == 0);
+ uint32_t data;
+ int status = dla_mmd_csr_read(handle_, instance, addr, &data);
+ assert(status == 0);
+ suppress_warning_unused_varible(status);
+ return data;
+}
+
+void MmdWrapper::WriteToDDR(int instance, uint64_t addr, uint64_t length, const void *data) const {
+ assert(instance >= 0 && instance < maxInstances_);
+ assert(addr + length <= ddrSizePerInstance_);
+ int status = dla_mmd_ddr_write(handle_, instance, addr, length, data);
+ assert(status == 0);
+ suppress_warning_unused_varible(status);
+}
+
+void MmdWrapper::ReadFromDDR(int instance, uint64_t addr, uint64_t length, void *data) const {
+ assert(instance >= 0 && instance < maxInstances_);
+ assert(addr + length <= ddrSizePerInstance_);
+ int status = dla_mmd_ddr_read(handle_, instance, addr, length, data);
+ assert(status == 0);
+ suppress_warning_unused_varible(status);
+}
+
+#ifndef STREAM_CONTROLLER_ACCESS
+// Stream controller access is not supported by the platform abstraction
+bool MmdWrapper::bIsStreamControllerValid(int instance) const { return false; }
+
+// 32-bit handshake with each Stream Controller CSR
+void MmdWrapper::WriteToStreamController(int instance, uint32_t addr, uint64_t length, const void *data) const {
+ assert(false);
+}
+
+void MmdWrapper::ReadFromStreamController(int instance, uint32_t addr, uint64_t length, void *data) const {
+ assert(false);
+}
+#else
+// If the mmd layer supports accesses to the Stream Controller
+bool MmdWrapper::bIsStreamControllerValid(int instance) const {
+ assert(instance >= 0 && instance < maxInstances_);
+ bool status = dla_is_stream_controller_valid(handle_, instance);
+ return status;
+}
+
+// 32-bit handshake with each Stream Controller CSR
+void MmdWrapper::WriteToStreamController(int instance, uint32_t addr, uint64_t length, const void *data) const {
+ assert(instance >= 0 && instance < maxInstances_);
+ assert(addr % sizeof(uint32_t) == 0);
+ assert(length % sizeof(uint32_t) == 0);
+ int status = dla_mmd_stream_controller_write(handle_, instance, addr, length, data);
+ assert(status == 0);
+ suppress_warning_unused_varible(status);
+}
+
+void MmdWrapper::ReadFromStreamController(int instance, uint32_t addr, uint64_t length, void *data) const {
+ assert(instance >= 0 && instance < maxInstances_);
+ assert(addr % sizeof(uint32_t) == 0);
+ assert(length % sizeof(uint32_t) == 0);
+ int status = dla_mmd_stream_controller_read(handle_, instance, addr, length, data);
+ assert(status == 0);
+ suppress_warning_unused_varible(status);
+}
+#endif