From 6dcae42b605344eaad9ab224b5969eb35eab4b13 Mon Sep 17 00:00:00 2001 From: philipp-weiss Date: Tue, 19 Dec 2017 10:37:17 +0100 Subject: [PATCH 1/2] Zynq Plugin --- CMakeLists.txt | 43 +++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 43 insertions(+) diff --git a/CMakeLists.txt b/CMakeLists.txt index 8d6670f..6ddfaa5 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -85,6 +85,8 @@ option(WARNINGS_ARE_ERRORS "Specify whether warnings should be treated as errors option(USE_AUTOMATIC_INITIALIZATION "Specify whether the MTAPI C++ interface, algorithms and dataflow should automatically intialize the MTAPI node if no explicit initialization is present" ON) option(BUILD_OPENCL_PLUGIN "Specify whether the MTAPI OpenCL plugin should be built" OFF) option(BUILD_CUDA_PLUGIN "Specify whether the MTAPI CUDA plugin should be built" OFF) +option(BUILD_PL_PLUGIN "Specify whether the MTAPI PL plugin should be built" ON) +option(BUILD_ZYNQ_PLUGIN "Specify whether the MTAPI Zynq plugin should be built" ON) option(THREADING_ANALYSIS_MODE "Replaces lock-free synchronization constructs by mutex-based implementations to support threading analysis tools" OFF) option(BUILD_SHARED_LIBS "Specify whether shared libs should be built" OFF) @@ -174,6 +176,38 @@ if(BUILD_OPENCL_PLUGIN STREQUAL ON) list(APPEND EXPECTED_EMBB_TEST_EXECUTABLES "embb_mtapi_opencl_c_test") endif() +if (BUILD_PL_PLUGIN STREQUAL ON) + message("-- Building PL plugin enabled") +else() + message("-- Building PL plugin disabled (default)") +endif() +message(" (set with command line option -DBUILD_PL_PLUGIN=ON/OFF)") + +if(BUILD_PL_PLUGIN STREQUAL ON) + list(APPEND EXPECTED_EMBB_TEST_EXECUTABLES "embb_mtapi_pl_c_test") +endif() + +if (BUILD_PL_2_PLUGIN STREQUAL ON) + message("-- Building PL 2 plugin enabled") +else() + message("-- Building PL 2 plugin disabled (default)") +endif() +message(" (set with command line option -DBUILD_PL_2_PLUGIN=ON/OFF)") +if(BUILD_PL_2_PLUGIN STREQUAL ON) + list(APPEND EXPECTED_EMBB_TEST_EXECUTABLES "embb_mtapi_pl_2_c_test") +endif() + +if (BUILD_ZYNQ_PLUGIN STREQUAL ON) + message("-- Building Zynq plugin enabled") +else() + message("-- Building Zynq plugin disabled (default)") +endif() +message(" (set with command line option -DBUILD_ZYNQ_PLUGIN=ON/OFF)") + +if(BUILD_ZYNQ_PLUGIN STREQUAL ON) + list(APPEND EXPECTED_EMBB_TEST_EXECUTABLES "embb_mtapi_zynq_c_test") +endif() + if (BUILD_CUDA_PLUGIN STREQUAL ON) message("-- Building CUDA plugin enabled") else() @@ -227,6 +261,15 @@ if(BUILD_CUDA_PLUGIN STREQUAL ON) add_subdirectory(mtapi_plugins_c/mtapi_cuda_c) endif() endif() +if(BUILD_PL_PLUGIN STREQUAL ON) + add_subdirectory(mtapi_plugins_c/mtapi_pl_c) +endif() +if(BUILD_PL_2_PLUGIN STREQUAL ON) + add_subdirectory(mtapi_plugins_c/mtapi_pl_2_c) +endif() +if(BUILD_ZYNQ_PLUGIN STREQUAL ON) + add_subdirectory(mtapi_plugins_c/mtapi_zynq_c) +endif() add_subdirectory(mtapi_cpp) add_subdirectory(containers_cpp) add_subdirectory(algorithms_cpp) From a3a1598848de91adfe3ea1c83eda8a478fca173b Mon Sep 17 00:00:00 2001 From: philipp-weiss Date: Tue, 19 Dec 2017 10:42:26 +0100 Subject: [PATCH 2/2] Zynq Plugin --- mtapi_plugins_c/mtapi_zynq_c/CMakeLists.txt | 58 ++ .../include/embb/mtapi/c/mtapi_zynq.h | 192 +++++++ .../mtapi_zynq_c/src/embb_mtapi_zynq.c | 538 ++++++++++++++++++ .../mtapi_zynq_c/src/embb_mtapi_zynq.h | 56 ++ .../mtapi_zynq_c/src/embb_mtapi_zynq_driver.c | 399 +++++++++++++ .../mtapi_zynq_c/src/embb_mtapi_zynq_driver.h | 117 ++++ .../src/embb_mtapi_zynq_task_queue.c | 118 ++++ .../src/embb_mtapi_zynq_task_queue.h | 104 ++++ .../src/embb_mtapi_zynq_task_queue_t_fwd.h | 44 ++ .../src/embb_mtapi_zynq_task_t_fwd.h | 44 ++ .../src/embb_mtapi_zynq_xlnk_ioctl.h | 117 ++++ mtapi_plugins_c/mtapi_zynq_c/src/exports.def | 5 + .../test/embb_mtapi_zynq_test_task.cc | 150 +++++ .../test/embb_mtapi_zynq_test_task.h | 40 ++ mtapi_plugins_c/mtapi_zynq_c/test/main.cc | 35 ++ 15 files changed, 2017 insertions(+) create mode 100644 mtapi_plugins_c/mtapi_zynq_c/CMakeLists.txt create mode 100644 mtapi_plugins_c/mtapi_zynq_c/include/embb/mtapi/c/mtapi_zynq.h create mode 100644 mtapi_plugins_c/mtapi_zynq_c/src/embb_mtapi_zynq.c create mode 100644 mtapi_plugins_c/mtapi_zynq_c/src/embb_mtapi_zynq.h create mode 100644 mtapi_plugins_c/mtapi_zynq_c/src/embb_mtapi_zynq_driver.c create mode 100644 mtapi_plugins_c/mtapi_zynq_c/src/embb_mtapi_zynq_driver.h create mode 100644 mtapi_plugins_c/mtapi_zynq_c/src/embb_mtapi_zynq_task_queue.c create mode 100644 mtapi_plugins_c/mtapi_zynq_c/src/embb_mtapi_zynq_task_queue.h create mode 100644 mtapi_plugins_c/mtapi_zynq_c/src/embb_mtapi_zynq_task_queue_t_fwd.h create mode 100644 mtapi_plugins_c/mtapi_zynq_c/src/embb_mtapi_zynq_task_t_fwd.h create mode 100644 mtapi_plugins_c/mtapi_zynq_c/src/embb_mtapi_zynq_xlnk_ioctl.h create mode 100644 mtapi_plugins_c/mtapi_zynq_c/src/exports.def create mode 100644 mtapi_plugins_c/mtapi_zynq_c/test/embb_mtapi_zynq_test_task.cc create mode 100644 mtapi_plugins_c/mtapi_zynq_c/test/embb_mtapi_zynq_test_task.h create mode 100644 mtapi_plugins_c/mtapi_zynq_c/test/main.cc diff --git a/mtapi_plugins_c/mtapi_zynq_c/CMakeLists.txt b/mtapi_plugins_c/mtapi_zynq_c/CMakeLists.txt new file mode 100644 index 0000000..78722bc --- /dev/null +++ b/mtapi_plugins_c/mtapi_zynq_c/CMakeLists.txt @@ -0,0 +1,58 @@ +project (project_embb_mtapi_zynq_c) + +file(GLOB_RECURSE EMBB_MTAPI_ZYNQ_C_SOURCES "src/*.c" "src/*.h") +file(GLOB_RECURSE EMBB_MTAPI_ZYNQ_C_HEADERS "include/*.h") + +file(GLOB_RECURSE EMBB_MTAPI_ZYNQ_TEST_SOURCES "test/*.cc" "test/*.h") + +IF(MSVC8 OR MSVC9 OR MSVC10 OR MSVC11) +FOREACH(src_tmp ${EMBB_MTAPI_ZYNQ_TEST_SOURCES}) + SET_PROPERTY(SOURCE ${src_tmp} PROPERTY LANGUAGE CXX) +ENDFOREACH(src_tmp) +FOREACH(src_tmp ${EMBB_MTAPI_ZYNQ_C_SOURCES}) + SET_PROPERTY(SOURCE ${src_tmp} PROPERTY LANGUAGE CXX) +ENDFOREACH(src_tmp) +ENDIF() + +IF(CMAKE_COMPILER_IS_GNUCC) + set (EMBB_MTAPI_ZYNQ_C_LIBS dl) +ENDIF() + +# Execute the GroupSources macro +include(${CMAKE_SOURCE_DIR}/CMakeCommon/GroupSourcesMSVC.cmake) +GroupSourcesMSVC(include) +GroupSourcesMSVC(src) +GroupSourcesMSVC(test) + +set (EMBB_MTAPI_ZYNQ_INCLUDE_DIRS "include" "src" "test") +include_directories(${EMBB_MTAPI_ZYNQ_INCLUDE_DIRS} + ${CMAKE_CURRENT_SOURCE_DIR}/../../base_c/include + ${CMAKE_CURRENT_BINARY_DIR}/../../base_c/include + ${CMAKE_CURRENT_SOURCE_DIR}/../../mtapi_c/include + ${CMAKE_CURRENT_SOURCE_DIR}/../../mtapi_c/src + ) + +add_library(embb_mtapi_zynq_c ${EMBB_MTAPI_ZYNQ_C_SOURCES} ${EMBB_MTAPI_ZYNQ_C_HEADERS}) +target_link_libraries(embb_mtapi_zynq_c embb_mtapi_c embb_base_c ) +if (BUILD_SHARED_LIBS STREQUAL ON) + if (MSVC) + set_target_properties(embb_mtapi_zynq_c PROPERTIES LINK_FLAGS "/DEF:\"${CMAKE_CURRENT_SOURCE_DIR}/src/exports.def\"") + CopyBin(BIN embb_mtapi_zynq_c DEST ${local_install_dir}) + endif() +endif() + +if (BUILD_TESTS STREQUAL ON) + include_directories(${CMAKE_CURRENT_BINARY_DIR}/../../partest/include) + add_executable (embb_mtapi_zynq_c_test ${EMBB_MTAPI_ZYNQ_TEST_SOURCES}) + target_link_libraries(embb_mtapi_zynq_c_test embb_mtapi_zynq_c embb_mtapi_c partest embb_base_c ${compiler_libs} ${EMBB_MTAPI_ZYNQ_C_LIBS}) + CopyBin(BIN embb_mtapi_zynq_c_test DEST ${local_install_dir}) +endif() + +install(DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/include/ + DESTINATION include FILES_MATCHING PATTERN "*.h") +install(TARGETS embb_mtapi_zynq_c EXPORT EMBB-Targets DESTINATION lib) +if (MSVC) + install(FILES ${CMAKE_CURRENT_BINARY_DIR}/Debug/embb_mtapi_zynq_c.pdb + DESTINATION lib + CONFIGURATIONS Debug) +endif() diff --git a/mtapi_plugins_c/mtapi_zynq_c/include/embb/mtapi/c/mtapi_zynq.h b/mtapi_plugins_c/mtapi_zynq_c/include/embb/mtapi/c/mtapi_zynq.h new file mode 100644 index 0000000..af77d64 --- /dev/null +++ b/mtapi_plugins_c/mtapi_zynq_c/include/embb/mtapi/c/mtapi_zynq.h @@ -0,0 +1,192 @@ +/* + * Copyright (c) 2014-2017, Siemens AG. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * 2. 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. + * + * 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 HOLDER 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. + */ + +#ifndef EMBB_MTAPI_C_MTAPI_ZYNQ_H_ +#define EMBB_MTAPI_C_MTAPI_ZYNQ_H_ + + +#include + + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * \defgroup C_MTAPI_ZYNQ MTAPI ZYNQ Plugin + * + * \ingroup C_MTAPI_EXT + * + * Provides functionality to execute tasks on Zynq devices. + */ + + +/** + * Initializes the MTAPI Zynq environment on a previously initialized MTAPI + * node. + * + * It must be called on all nodes using the MTAPI Zynq plugin. + * + * Application software using MTAPI Zynq must call + * mtapi_zynq_plugin_initialize() once per node. It is an error to call + * mtapi_zynq_plugin_initialize() multiple times + * from a given node, unless mtapi_zynq_plugin_finalize() is called in + * between. + * + * On success, \c *status is set to \c MTAPI_SUCCESS. On error, \c *status is + * set to the appropriate error defined below. + * Error code | Description + * --------------------------- | ---------------------------------------------- + * \c MTAPI_ERR_UNKNOWN | MTAPI Zynq couldn't be initialized. + * + * \see mtapi_zynq_plugin_finalize() + * + * \notthreadsafe + * \ingroup C_MTAPI_ZYNQ + */ +void mtapi_zynq_plugin_initialize( + MTAPI_IN char* uio_name, /**< [out] UIO device tree name */ + MTAPI_OUT mtapi_status_t* status /**< [out] Pointer to error code, + may be \c MTAPI_NULL */ +); + +/** + * Finalizes the MTAPI Zynq environment on the local MTAPI node. + * + * It has to be called by each node using MTAPI Zynq. It is an error to call + * mtapi_zynq_plugin_finalize() without first calling + * mtapi_zynq_plugin_initialize(). An MTAPI node can call + * mtapi_zynq_plugin_finalize() once for each call to + * mtapi_zynq_plugin_initialize(), but it is an error to call + * mtapi_zynq_plugin_finalize() multiple times from a given node + * unless mtapi_zynq_plugin_initialize() has been called prior to each + * mtapi_zynq_plugin_finalize() call. + * + * All Zynq tasks that have not completed and that have been started on the + * node where mtapi_zynq_plugin_finalize() is called will be canceled + * (see mtapi_task_cancel()). mtapi_zynq_plugin_finalize() blocks until all + * tasks that have been started on the same node return. Tasks that execute + * actions on the node where mtapi_zynq_plugin_finalize() is called, also + * block finalization of the MTAPI Zynq system on that node. + * + * On success, \c *status is set to \c MTAPI_SUCCESS. On error, \c *status is + * set to the appropriate error defined below. + * Error code | Description + * ----------------------------- | -------------------------------------------- + * \c MTAPI_ERR_UNKNOWN | MTAPI Zynq couldn't be finalized. + * + * \see mtapi_zynq_plugin_initialize(), mtapi_task_cancel() + * + * \notthreadsafe + * \ingroup C_MTAPI_ZYNQ + */ +void mtapi_zynq_plugin_finalize( + MTAPI_OUT mtapi_status_t* status /**< [out] Pointer to error code, + may be \c MTAPI_NULL */ +); + +/** + * This function creates a ZYNQ action. + * + * It is called on the node where the user wants to execute an action on a + * Zynq device. A Zynq action contains a reference to a local job and the physical + * address of an accelerator in the programmable logic. + * After a Zynq action is created, it is referenced by the application using + * a node-local handle of type \c mtapi_action_hndl_t, or indirectly through a + * node-local job handle of type \c mtapi_job_hndl_t. A Zynq action's + * life-cycle begins with mtapi_zynq_action_create(), and ends when + * mtapi_action_delete() or mtapi_finalize() is called. + * + * To create an action, the application must supply the domain-wide job ID of + * the job associated with the action. Job IDs must be predefined in the + * application and runtime, of type \c mtapi_job_id_t, which is an + * implementation-defined type. The job ID is unique in the sense that it is + * unique for the job implemented by the action. However several actions may + * implement the same job for load balancing purposes. + * + * If \c node_local_data_size is not zero, \c node_local_data specifies the + * start of node local data shared by kernel functions executed on the same + * node. \c node_local_data_size can be used by the runtime for cache coherency + * operations. + * + * On success, an action handle is returned and \c *status is set to + * \c MTAPI_SUCCESS. On error, \c *status is set to the appropriate error + * defined below. In the case where the action already exists, \c status will + * be set to \c MTAPI_ERR_ACTION_EXISTS and the handle returned will not be a + * valid handle. + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + *
Error codeDescription
\c MTAPI_ERR_JOB_INVALIDThe \c job_id is not a valid job ID, i.e., no action was created for + * that ID or the action has been deleted.
\c MTAPI_ERR_ACTION_EXISTSThis action is already created.
\c MTAPI_ERR_ACTION_LIMITExceeded maximum number of actions allowed.
\c MTAPI_ERR_NODE_NOTINITThe calling node is not initialized.
\c MTAPI_ERR_UNKNOWNThe kernel could not be compiled or no OpenCL device was + * available.
+ * + * \see mtapi_action_delete(), mtapi_finalize() + * + * \returns Handle to newly created Zynq action, invalid handle on error + * \threadsafe + * \ingroup C_MTAPI_ZYNQ + */ +mtapi_action_hndl_t mtapi_zynq_action_create( + MTAPI_IN mtapi_job_id_t job_id, /**< [in] Job id */ + MTAPI_IN char* uio_name, /**< [in] Name of the UIO node in the device tree, may be \c MTAPI_NULL to use /dev/mem for memory mapping*/ + MTAPI_IN uint32_t phys_addr, /**< [in] Physical address of the accelerator*/ + MTAPI_IN void* node_local_data, /**< [in] Data shared across tasks */ + MTAPI_IN mtapi_size_t node_local_data_size, + /**< [in] Size of shared data */ + MTAPI_IN uint8_t cacheable, /**< [in] Defines whether buffers are cached or not*/ + MTAPI_OUT mtapi_status_t* status /**< [out] Pointer to error code, + may be \c MTAPI_NULL */ +); + +#ifdef __cplusplus +} +#endif + + +#endif // EMBB_MTAPI_C_MTAPI_ZYNQ_H_ diff --git a/mtapi_plugins_c/mtapi_zynq_c/src/embb_mtapi_zynq.c b/mtapi_plugins_c/mtapi_zynq_c/src/embb_mtapi_zynq.c new file mode 100644 index 0000000..1bf937c --- /dev/null +++ b/mtapi_plugins_c/mtapi_zynq_c/src/embb_mtapi_zynq.c @@ -0,0 +1,538 @@ +/* + * Copyright (c) 2017, Siemens AG. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * 2. 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. + * + * 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 HOLDER 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 + +#include +#include +#include + +#include + +#include + +/* Inline Functions */ +#define write_32bit_reg(base_address, reg_offset, data) \ + *(volatile uint32_t*)((base_address) + (reg_offset >> 2)) = (uint32_t)(data) +#define read_32bit_reg(base_address, reg_offset) \ + *(volatile uint32_t*)((base_address) + (reg_offset >> 2)) + +/* Macros */ +#define MAX_UIO_PATH_SIZE 64 +#define MAX_UIO_DEVICES 64 +#define MAP_SIZE 0x1000 + +/* Accelerator Control Interface Offsets */ +#define CONTROL_ADDR_AP_CTRL 0x00 +#define CONTROL_ADDR_GIE 0x04 +#define CONTROL_ADDR_IER 0x08 +#define CONTROL_ADDR_ISR 0x0c +#define CONTROL_ADDR_CONFIG 0x10 +#define CONTROL_BITS_CONFIG 32 +#define CONTROL_ADDR_ARGUMENTS 0x18 +#define CONTROL_BITS_ARGUMENTS 32 +#define CONTROL_ADDR_ARGUMENTS_SIZE 0x20 +#define CONTROL_BITS_ARGUMENTS_SIZE 32 +#define CONTROL_ADDR_RESULT_BUFFER 0x28 +#define CONTROL_BITS_RESULT_BUFFER 32 +#define CONTROL_ADDR_RESULT_BUFFER_SIZE 0x30 +#define CONTROL_BITS_RESULT_BUFFER_SIZE 32 +#define CONTROL_ADDR_NODE_LOCAL_DATA 0x38 +#define CONTROL_BITS_NODE_LOCAL_DATA 32 +#define CONTROL_ADDR_NODE_LOCAL_DATA_SIZE 0x40 +#define CONTROL_BITS_NODE_LOCAL_DATA_SIZE 32 + +static uio_info_t uio_base; + +struct embb_mtapi_zynq_action_struct { + acc_t accelerator; + embb_thread_t thread; + embb_atomic_int run; + embb_mtapi_zynq_task_queue_t zynq_task_queue; + // file which is used to wait for interrupt + const void* node_local_data; + mtapi_size_t node_local_data_size; + cma_buffer_t cma_node_local_data; + mtapi_boolean_t cacheable; +}; +typedef struct embb_mtapi_zynq_action_struct embb_mtapi_zynq_action_t; + +static void zynq_load_node_local_data(embb_mtapi_zynq_action_t* action); +static void zynq_task_complete(embb_mtapi_zynq_task_t* zynq_task); +static void zynq_task_start(acc_t* accelerator, embb_mtapi_zynq_task_t* zynq_task); + +static int embb_mtapi_zynq_thread(void* arguments){ + embb_mtapi_zynq_action_t* action = (embb_mtapi_zynq_action_t*) arguments; + embb_mtapi_zynq_task_t* zynq_task; + + if(action->node_local_data_size > 0){ + zynq_load_node_local_data(action); + } + + while(embb_atomic_load_int(&action->run) == 1){ + + zynq_task = embb_mtapi_zynq_task_queue_pop_front(&action->zynq_task_queue); + if(zynq_task != NULL){ + + + uio_enable_interrupt(&action->accelerator.uio_fd); + zynq_task_start(&action->accelerator, zynq_task); + uio_wait_interrupt(&action->accelerator.uio_fd); + + if(acc_interrupt_read(&action->accelerator) == 0x00){ + do{ + uio_enable_interrupt(&action->accelerator.uio_fd); + uio_wait_interrupt(&action->accelerator.uio_fd); + }while(acc_interrupt_read(&action->accelerator) == 0x00); + } + + acc_interrupt_clear(&action->accelerator); + zynq_task_complete(zynq_task); + + } + else{ + embb_thread_yield(); + } + } + return 0; +} + +static void zynq_load_node_local_data(embb_mtapi_zynq_action_t* action){ + + assert(action->cma_node_local_data.virt_addr != NULL); + assert(action->node_local_data != NULL); + memcpy(action->cma_node_local_data.virt_addr, action->node_local_data, action->node_local_data_size); + + acc_write_node_local_data_addr(&action->accelerator, &action->cma_node_local_data); + acc_write_node_local_data_size(&action->accelerator, action->node_local_data_size); + + uint32_t* ptr = action->cma_node_local_data.virt_addr; + printf("node_local_data: %d\n", ptr[0]); + + uint32_t reg; + reg = read_32bit_reg(action->accelerator.control_base_address, CONTROL_ADDR_AP_CTRL); + printf("CONTROL_ADDR_AP_CTRL: %x\n", reg); + reg = read_32bit_reg(action->accelerator.control_base_address, CONTROL_ADDR_GIE); + printf("CONTROL_ADDR_GIE: %x\n", reg); + reg = read_32bit_reg(action->accelerator.control_base_address, CONTROL_ADDR_IER); + printf("CONTROL_ADDR_IER: %x\n", reg); + reg = read_32bit_reg(action->accelerator.control_base_address, CONTROL_ADDR_ISR); + printf("CONTROL_ADDR_ISR: %x\n", reg); + reg = read_32bit_reg(action->accelerator.control_base_address, CONTROL_ADDR_CONFIG); + printf("CONTROL_ADDR_CONFIG: %x\n", reg); + reg = read_32bit_reg(action->accelerator.control_base_address, CONTROL_ADDR_ARGUMENTS); + printf("CONTROL_ADDR_ARGUMENTS: %x\n", reg); + reg = read_32bit_reg(action->accelerator.control_base_address, CONTROL_ADDR_ARGUMENTS_SIZE); + printf("CONTROL_ADDR_ARGUMENTS_SIZE: %x\n", reg); + reg = read_32bit_reg(action->accelerator.control_base_address, CONTROL_ADDR_RESULT_BUFFER); + printf("CONTROL_ADDR_RESULT_BUFFER: %x\n", reg); + reg = read_32bit_reg(action->accelerator.control_base_address, CONTROL_ADDR_RESULT_BUFFER_SIZE); + printf("CONTROL_ADDR_RESULT_BUFFER_SIZE: %x\n", reg); + reg = read_32bit_reg(action->accelerator.control_base_address, CONTROL_ADDR_NODE_LOCAL_DATA); + printf("CONTROL_ADDR_NODE_LOCAL_DATA: %x\n", reg); + reg = read_32bit_reg(action->accelerator.control_base_address, CONTROL_ADDR_NODE_LOCAL_DATA_SIZE); + printf("CONTROL_ADDR_NODE_LOCAL_DATA_SIZE: %x\n", reg); + + // change mode to load node local data + acc_write_config(&action->accelerator, 0x01); + + uio_enable_interrupt(&action->accelerator.uio_fd); + printf("Start accelerator\n"); + acc_start(&action->accelerator); + uio_wait_interrupt(&action->accelerator.uio_fd); + if(acc_interrupt_read(&action->accelerator) == 0x00){ + do{ + uio_enable_interrupt(&action->accelerator.uio_fd); + uio_wait_interrupt(&action->accelerator.uio_fd); + }while(acc_interrupt_read(&action->accelerator) == 0x00); + } + acc_interrupt_clear(&action->accelerator); + + // change back to normal mode + acc_write_config(&action->accelerator, 0x00); + printf("Node local data done\n"); +} + +static void zynq_task_complete(embb_mtapi_zynq_task_t* zynq_task) { + int err = 0; + if (embb_mtapi_node_is_initialized()){ + embb_mtapi_node_t * node = embb_mtapi_node_get_instance(); + + if (embb_mtapi_task_pool_is_handle_valid(node->task_pool, zynq_task->task)){ + embb_mtapi_task_t * local_task = + embb_mtapi_task_pool_get_storage_for_handle(node->task_pool, zynq_task->task); + + // move result and free cma buffers + if(local_task->result_size > 0){ + assert(zynq_task->cma_result_buffer.virt_addr != NULL); + + memcpy(local_task->result_buffer, zynq_task->cma_result_buffer.virt_addr, local_task->result_size); + + err = cma_free_buf(&zynq_task->cma_result_buffer); + + } + + if(local_task->arguments_size > 0){ + err |= cma_free_buf(&zynq_task->cma_arguments); + } + + if(err != 0){ + printf("ERROR: Could not free CMA buffers!\r\n"); + } + // free task + embb_free(zynq_task); + + // decrease action num + if (embb_mtapi_action_pool_is_handle_valid( + node->action_pool, local_task->action)) { + embb_mtapi_action_t * local_action = + embb_mtapi_action_pool_get_storage_for_handle( + node->action_pool, local_task->action); + + embb_atomic_fetch_and_add_int(&local_action->num_tasks, + -(int)local_task->attributes.num_instances); + } + + // set status + embb_mtapi_task_set_state(local_task, MTAPI_TASK_COMPLETED); + + if (MTAPI_NULL != local_task->attributes.complete_func) { + local_task->attributes.complete_func(zynq_task->task, MTAPI_NULL); + } + + } + } +} + +static void zynq_task_start(acc_t* accelerator, embb_mtapi_zynq_task_t* zynq_task){ + + if(embb_mtapi_node_is_initialized()){ + embb_mtapi_node_t * node = embb_mtapi_node_get_instance(); + + if(embb_mtapi_task_pool_is_handle_valid( + node->task_pool, zynq_task->task)){ + embb_mtapi_task_t * local_task = + embb_mtapi_task_pool_get_storage_for_handle( + node->task_pool, zynq_task->task); + + if(local_task->arguments_size > 0){ + assert(zynq_task->cma_arguments.virt_addr != NULL); + assert(local_task->arguments != NULL); + // copy arguments + + memcpy(zynq_task->cma_arguments.virt_addr, local_task->arguments, local_task->arguments_size); + + // write arguments physical address + acc_write_arguments_addr(accelerator, &zynq_task->cma_arguments); + } + if(local_task->result_size > 0){ + // write result buffer physical address + acc_write_result_addr(accelerator, &zynq_task->cma_result_buffer); + } + acc_write_arguments_size(accelerator, local_task->arguments_size); + acc_write_result_size(accelerator, local_task->result_size); + + // start accelerator + acc_start(accelerator); + } + } + +} + +/** + * Represents a callback function that is called when a plugin action is about + * to start a plugin task. + * This function should return MTAPI_SUCCESS if the task could be started and + * the appropriate MTAPI_ERR_* if not. + */ + +static void zynq_task_enqueue( + MTAPI_IN mtapi_task_hndl_t task, + MTAPI_OUT mtapi_status_t* status){ + mtapi_status_t local_status = MTAPI_ERR_UNKNOWN; + int err = 0; + + if (embb_mtapi_node_is_initialized()) { + embb_mtapi_node_t * node = embb_mtapi_node_get_instance(); + + if (embb_mtapi_task_pool_is_handle_valid(node->task_pool, task)) { + embb_mtapi_task_t * local_task = + embb_mtapi_task_pool_get_storage_for_handle(node->task_pool, task); + + if (embb_mtapi_action_pool_is_handle_valid( + node->action_pool, local_task->action)) { + embb_mtapi_action_t * local_action = + embb_mtapi_action_pool_get_storage_for_handle( + node->action_pool, local_task->action); + + embb_mtapi_zynq_action_t * zynq_action = + (embb_mtapi_zynq_action_t*)local_action->plugin_data; + embb_mtapi_zynq_task_t * zynq_task = + (embb_mtapi_zynq_task_t*)embb_alloc( + sizeof(embb_mtapi_zynq_task_t)); + + + zynq_task->task = task; + // Allocate CMA buffers + + if(0 < local_task->arguments_size){ + zynq_task->cma_arguments.len = (uint32_t)local_task->arguments_size; + zynq_task->cma_arguments.cacheable = zynq_action->cacheable; + err = cma_alloc_buf(&zynq_task->cma_arguments); + } + else{ + zynq_task->cma_arguments.virt_addr = NULL; + } + if(err != 0){ + printf("ERROR: Failed to allocate CMA buffer! \r\n"); + embb_mtapi_task_set_state(local_task, MTAPI_TASK_ERROR); + local_status = MTAPI_ERR_ACTION_FAILED; + mtapi_status_set(status, local_status); + return; + } + + if(0 < local_task->result_size){ + zynq_task->cma_result_buffer.len = (uint32_t)local_task->result_size; + zynq_task->cma_result_buffer.cacheable = zynq_action->cacheable; + err |= cma_alloc_buf(&zynq_task->cma_result_buffer); + } + else { + zynq_task->cma_result_buffer.virt_addr = NULL; + } + + if(err != 0){ + printf("ERROR: Failed to allocate CMA buffer! \r\n"); + cma_free_buf(&zynq_task->cma_arguments); + embb_mtapi_task_set_state(local_task, MTAPI_TASK_ERROR); + local_status = MTAPI_ERR_ACTION_FAILED; + mtapi_status_set(status, local_status); + return; + } + + embb_mtapi_zynq_task_queue_push_back(&zynq_action->zynq_task_queue, zynq_task); + + + embb_mtapi_task_set_state(local_task, MTAPI_TASK_RUNNING); + // start + if (0 != err) { + printf("ERROR IN TASK ENQUEUE \r\n"); + embb_mtapi_task_set_state(local_task, MTAPI_TASK_ERROR); + local_status = MTAPI_ERR_ACTION_FAILED; + } + else{ + local_status = MTAPI_SUCCESS; + } + } + } + } + mtapi_status_set(status, local_status); + +} + +/** + * Represents a callback function that is called when a plugin task is about + * to be canceled. + * This function should return MTAPI_SUCCESS if the task could be canceled and + * the appropriate MTAPI_ERR_* if not. + * Not possible to cancel a task! + */ +static void zynq_task_cancel( + MTAPI_IN mtapi_task_hndl_t task, + MTAPI_OUT mtapi_status_t* status){ + mtapi_status_t local_status = MTAPI_ERR_UNKNOWN; + + EMBB_UNUSED(task); + mtapi_status_set(status, local_status); +} + + +void mtapi_zynq_plugin_initialize( + MTAPI_IN char* uio_name, + MTAPI_OUT mtapi_status_t* status) { + mtapi_status_t local_status = MTAPI_ERR_UNKNOWN; + + // initialize uio interrupt controller + if(strlen(uio_name)>MAX_UIO_NAME_SIZE){ + printf("ERROR: uio name too long\r\n"); + } + else{ + strcpy(uio_base.uio_name, uio_name); + + if (uio_initialize(uio_base.uio_name, &uio_base.uio_id) == 0){ + local_status = MTAPI_SUCCESS; + } + } + + mtapi_status_set(status, local_status); +} + +void mtapi_zynq_plugin_finalize( + MTAPI_OUT mtapi_status_t* status) { + mtapi_status_t local_status = MTAPI_ERR_UNKNOWN; + + local_status = MTAPI_SUCCESS; + mtapi_status_set(status, local_status); +} + +// destroy objects +static void zynq_action_finalize( + MTAPI_IN mtapi_action_hndl_t action, + MTAPI_OUT mtapi_status_t* status + ) { + mtapi_status_t local_status = MTAPI_ERR_UNKNOWN; + int err; + if (embb_mtapi_node_is_initialized()) { + embb_mtapi_node_t * node = embb_mtapi_node_get_instance(); + if (embb_mtapi_action_pool_is_handle_valid(node->action_pool, action)) { + embb_mtapi_action_t * local_action = + embb_mtapi_action_pool_get_storage_for_handle( + node->action_pool, action); + embb_mtapi_zynq_action_t * zynq_action = + (embb_mtapi_zynq_action_t *)local_action->plugin_data; + + // join thread + embb_atomic_store_int(&zynq_action->run, 0); + embb_thread_join(&zynq_action->thread, &err); + embb_atomic_destroy_int(&zynq_action->run); + + acc_interrupt_done_disable(&zynq_action->accelerator); + acc_interrupt_global_disable(&zynq_action->accelerator); + + uio_close(&zynq_action->accelerator.uio_fd); + if(zynq_action->accelerator.uio_name == MTAPI_NULL){ + acc_release(&zynq_action->accelerator); + } + else{ + uio_release(&zynq_action->accelerator); + } + + embb_mtapi_zynq_task_queue_finalize(&zynq_action->zynq_task_queue); + + if(zynq_action->node_local_data_size > 0){ + err |= cma_free_buf(&zynq_action->cma_node_local_data); + } + + embb_free(zynq_action); + local_status = MTAPI_SUCCESS; + } + } + + mtapi_status_set(status, local_status); +} + +mtapi_action_hndl_t mtapi_zynq_action_create( + MTAPI_IN mtapi_job_id_t job_id, + MTAPI_IN char* uio_name, + MTAPI_IN uint32_t phys_addr, + MTAPI_IN void* node_local_data, + MTAPI_IN mtapi_size_t node_local_data_size, + MTAPI_IN mtapi_boolean_t cacheable, + MTAPI_OUT mtapi_status_t* status){ + + + int err; + err = 0; + mtapi_status_t local_status = MTAPI_ERR_UNKNOWN; + + embb_mtapi_zynq_action_t * action = + (embb_mtapi_zynq_action_t*)embb_alloc( + sizeof(embb_mtapi_zynq_action_t)); + + mtapi_action_hndl_t action_hndl = { 0, 0 }; // invalid handle + + embb_atomic_init_int(&action->run, 0); + action->accelerator.phys_address = phys_addr; + action->cacheable = cacheable; + + if(uio_name == MTAPI_NULL){ + // Use dev/mem for memory mapping + printf("Use /dev/mem \n"); + acc_initialize(&action->accelerator); + err |= uio_open(&action->accelerator.uio_fd, &uio_base.uio_id); + } + else{ + // Use uio for memory mapping + if(strlen(uio_name)>MAX_UIO_NAME_SIZE){ + printf("ERROR: uio name too long\r\n"); + return action_hndl; + } + strcpy(action->accelerator.uio_name, uio_name); + // find uio id + uio_initialize(action->accelerator.uio_name, &action->accelerator.uio_id); + uio_open(&action->accelerator.uio_fd, &action->accelerator.uio_id); + printf("Use UIO mapping \n"); + uio_mmap(&action->accelerator); + } + acc_interrupt_clear(&action->accelerator); + acc_interrupt_done_enable(&action->accelerator); + acc_interrupt_global_enable(&action->accelerator); + + embb_mtapi_zynq_task_queue_initialize(&action->zynq_task_queue); + + + action->node_local_data = node_local_data; + action->node_local_data_size = node_local_data_size; + if(node_local_data_size > 0){ + action->cma_node_local_data.len = (uint32_t)node_local_data_size; + action->cma_node_local_data.cacheable = action->cacheable; + err |= cma_alloc_buf(&action->cma_node_local_data); + } + else{ + action->cma_node_local_data.virt_addr = NULL; + } + + embb_atomic_store_int(&action->run, 1); + err |= embb_thread_create(&action->thread, NULL, embb_mtapi_zynq_thread, (void*)action); + + if(err != 0){ + printf("ERROR in action create r\n"); + } + + action_hndl = mtapi_ext_plugin_action_create( + job_id, + zynq_task_enqueue, + zynq_task_cancel, + zynq_action_finalize, + action, + node_local_data, + node_local_data_size, + MTAPI_NULL, + &local_status); + + mtapi_status_set(status, local_status); + + return action_hndl; +} \ No newline at end of file diff --git a/mtapi_plugins_c/mtapi_zynq_c/src/embb_mtapi_zynq.h b/mtapi_plugins_c/mtapi_zynq_c/src/embb_mtapi_zynq.h new file mode 100644 index 0000000..1736462 --- /dev/null +++ b/mtapi_plugins_c/mtapi_zynq_c/src/embb_mtapi_zynq.h @@ -0,0 +1,56 @@ +/* + * Copyright (c) 2014-2017, Siemens AG. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * 2. 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. + * + * 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 HOLDER 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. + */ + +#ifndef EMBB_MTAPI_ZYNQ_H_ +#define EMBB_MTAPI_ZYNQ_H_ + +#include + +#ifdef __cplusplus +extern "C" { +#endif + + +/* ---- FORWARD DECLARATIONS ----------------------------------------------- */ + + + +/* ---- TYPE DEFINITIONS --------------------------------------------------- */ + +struct embb_mtapi_zynq_task_struct { + cma_buffer_t cma_arguments; + cma_buffer_t cma_result_buffer; + mtapi_task_hndl_t task; + struct embb_mtapi_zynq_task_struct* next; +}; + +#include + +#ifdef __cplusplus +} +#endif + +#endif // EMBB_MTAPI_ZYNQ_H_ \ No newline at end of file diff --git a/mtapi_plugins_c/mtapi_zynq_c/src/embb_mtapi_zynq_driver.c b/mtapi_plugins_c/mtapi_zynq_c/src/embb_mtapi_zynq_driver.c new file mode 100644 index 0000000..3c4dac0 --- /dev/null +++ b/mtapi_plugins_c/mtapi_zynq_c/src/embb_mtapi_zynq_driver.c @@ -0,0 +1,399 @@ +/* + * Copyright (c) 2017, Siemens AG. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * 2. 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. + * + * 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 HOLDER 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. + */ + +// wann assert, wann status = ERROR ? + +#define _SVID_SOURCE + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +#include + + #include + +/*************************************************************************/ +/* Inline Functions */ +#define write_32bit_reg(base_address, reg_offset, data) \ + *(volatile uint32_t*)((base_address) + (reg_offset >> 2)) = (uint32_t)(data) +#define read_32bit_reg(base_address, reg_offset) \ + *(volatile uint32_t*)((base_address) + (reg_offset >> 2)) + +/* Macros */ +#define MAX_UIO_PATH_SIZE 64 +#define MAX_UIO_DEVICES 64 +#define MAP_SIZE 0x1000 + +/* Accelerator Control Interface Offsets */ +#define CONTROL_ADDR_AP_CTRL 0x00 +#define CONTROL_ADDR_GIE 0x04 +#define CONTROL_ADDR_IER 0x08 +#define CONTROL_ADDR_ISR 0x0c +#define CONTROL_ADDR_CONFIG 0x10 +#define CONTROL_BITS_CONFIG 32 +#define CONTROL_ADDR_ARGUMENTS 0x18 +#define CONTROL_BITS_ARGUMENTS 32 +#define CONTROL_ADDR_ARGUMENTS_SIZE 0x20 +#define CONTROL_BITS_ARGUMENTS_SIZE 32 +#define CONTROL_ADDR_RESULT_BUFFER 0x28 +#define CONTROL_BITS_RESULT_BUFFER 32 +#define CONTROL_ADDR_RESULT_BUFFER_SIZE 0x30 +#define CONTROL_BITS_RESULT_BUFFER_SIZE 32 +#define CONTROL_ADDR_NODE_LOCAL_DATA 0x38 +#define CONTROL_BITS_NODE_LOCAL_DATA 32 +#define CONTROL_ADDR_NODE_LOCAL_DATA_SIZE 0x40 +#define CONTROL_BITS_NODE_LOCAL_DATA_SIZE 32 + + +/*************************************************************************/ +/* Xlnk Driver Functions */ + +int cma_alloc_buf(cma_buffer_t* cma_buf){ + union xlnk_arguments_u xlnk_arguments; + char file[10]; + int fd; + int err; + uint8_t rest = 0; +#if __SIZEOF_POINTER__ == 4 + rest = cma_buf->len % 4; +#elif __SIZEOF_POINTER__ == 8 + rest = cma_buf->len % 8; +#endif + + xlnk_arguments.allocate_buffer.len = cma_buf->len + rest; + xlnk_arguments.allocate_buffer.cacheable = cma_buf->cacheable; + + sprintf(file, "/dev/xlnk"); + if ((fd = open(file, O_RDWR)) < 0) { + printf("ERROR: Could not open file: %s \n", file); + return 1; + } + + err = ioctl(fd, ALLOCATE_CMA_BUFFER, &xlnk_arguments); + + if(!err){ + cma_buf->phys_addr = xlnk_arguments.allocate_buffer.phys_addr; + cma_buf->id = xlnk_arguments.allocate_buffer.id; + // buf_id << (16-PAGE_SHIFT) = 4 + uint32_t page_size = getpagesize(); + uint32_t page_shift; + for(page_shift=0; page_shift<32; page_shift++){ + page_size = page_size >> 1; + if(page_size == 0x1){ + break; + } + } + page_shift+=1; + // TODO + cma_buf->virt_addr = (uint32_t*)mmap(NULL, cma_buf->len + rest, PROT_READ|PROT_WRITE, MAP_SHARED, fd, cma_buf->id << (page_shift+4)); + } + + close(fd); + + return err; +} + +int cma_free_buf(cma_buffer_t* cma_buf){ + union xlnk_arguments_u xlnk_arguments; + char file[10]; + int fd; + int err; + + uint8_t rest = 0; +#if __SIZEOF_POINTER__ == 4 + rest = cma_buf->len % 4; +#elif __SIZEOF_POINTER__ == 8 + rest = cma_buf->len % 8; +#endif + + if(cma_buf->virt_addr == NULL){ + return 1; + } + + munmap((void*)cma_buf->virt_addr, cma_buf->len + rest); + + xlnk_arguments.free_buffer.id = cma_buf->id; + + sprintf(file, "/dev/xlnk"); + if ((fd = open(file, O_RDWR)) < 0) { + printf("ERROR: Could not open file: %s \n", file); + return 1; + } + + err = ioctl(fd, FREE_CMA_BUFFER, &xlnk_arguments); + close(fd); + + return err; +} + +/*************************************************************************/ +/* MTAPI FPGA Accelerator Driver Functions */ + +int acc_initialize(acc_t* acc){ + char file[10]; + int fd; + + assert(acc != NULL); + sprintf(file, "/dev/mem"); + if ((fd = open(file, O_RDWR)) < 0) { + printf("ERROR: Could not open file: %s \n", file); + return 1; + } + + //acc->control_base_address = (uint32_t*)cma_mmap((unsigned long)acc->phys_address, MAP_SIZE); + + unsigned page_addr = (acc->phys_address & (~(getpagesize()-1))); + unsigned page_offset = acc->phys_address - page_addr; + + acc->control_base_address = (uint32_t*)mmap(NULL, MAP_SIZE, PROT_READ|PROT_WRITE, MAP_SHARED, fd, page_addr); + acc->control_base_address+= page_offset; + + close(fd); + return 0; +} + +int acc_release(acc_t* acc){ + assert(acc != NULL); + munmap((void*)acc->control_base_address, MAP_SHARED); + return 0; +} + +void acc_interrupt_global_disable(acc_t* acc){ + assert(acc != NULL); + write_32bit_reg(acc->control_base_address, CONTROL_ADDR_GIE, 0x0); +} + +void acc_interrupt_global_enable(acc_t* acc){ + assert(acc != NULL); + write_32bit_reg(acc->control_base_address, CONTROL_ADDR_GIE, 0x1); +} + +void acc_interrupt_done_enable(acc_t* acc){ + assert(acc != NULL); + write_32bit_reg(acc->control_base_address, CONTROL_ADDR_IER, 0x1); +} + +void acc_interrupt_done_disable(acc_t* acc){ + assert(acc != NULL); + write_32bit_reg(acc->control_base_address, CONTROL_ADDR_IER, 0x0); +} + +void acc_interrupt_clear(acc_t* acc){ + assert(acc != NULL); + uint32_t reg; + reg = read_32bit_reg(acc->control_base_address, CONTROL_ADDR_ISR); + write_32bit_reg(acc->control_base_address, CONTROL_ADDR_ISR, reg); +} + +uint32_t acc_interrupt_read(acc_t* acc){ + assert(acc != NULL); + return read_32bit_reg(acc->control_base_address, CONTROL_ADDR_ISR); +} + +void acc_start(acc_t* acc){ + assert(acc != NULL); + write_32bit_reg(acc->control_base_address, CONTROL_ADDR_AP_CTRL, 0x01); +} + +void acc_write_arguments_addr(acc_t* acc, cma_buffer_t* cma_arguments){ + assert(acc != NULL); + assert(cma_arguments != NULL); + write_32bit_reg(acc->control_base_address, CONTROL_ADDR_ARGUMENTS, (uint32_t) cma_arguments->phys_addr); +} + +void acc_write_arguments_size(acc_t* acc, uint32_t arguments_size){ + assert(acc != NULL); + write_32bit_reg(acc->control_base_address, CONTROL_ADDR_ARGUMENTS_SIZE, arguments_size); +} + +void acc_write_result_addr(acc_t* acc, cma_buffer_t* cma_result_buffer){ + assert(acc != NULL); + assert(cma_result_buffer != NULL); + write_32bit_reg(acc->control_base_address, CONTROL_ADDR_RESULT_BUFFER, (uint32_t) cma_result_buffer->phys_addr); +} + +void acc_write_result_size(acc_t* acc, uint32_t result_size){ + assert(acc != NULL); + write_32bit_reg(acc->control_base_address, CONTROL_ADDR_RESULT_BUFFER_SIZE, result_size); +} + +void acc_write_node_local_data_addr(acc_t* acc, cma_buffer_t* cma_node_local_data){ + assert(acc != NULL); + assert(cma_node_local_data != NULL); + write_32bit_reg(acc->control_base_address, CONTROL_ADDR_NODE_LOCAL_DATA, (uint32_t) cma_node_local_data->phys_addr); +} + +void acc_write_node_local_data_size(acc_t* acc, uint32_t node_local_data_size){ + assert(acc != NULL); + write_32bit_reg(acc->control_base_address, CONTROL_ADDR_NODE_LOCAL_DATA_SIZE, node_local_data_size); +} + +void acc_write_config(acc_t* acc, uint32_t reg){ + assert(acc != NULL); + write_32bit_reg(acc->control_base_address, CONTROL_ADDR_CONFIG, reg); +} + + + +/* UIO Driver Functions */ + +void uio_mmap(acc_t* acc){ + assert(acc->uio_fd != NULL); + acc->control_base_address = (uint32_t*)mmap(NULL, MAP_SIZE, PROT_READ|PROT_WRITE, MAP_SHARED, acc->uio_fd, 0* getpagesize()); +} + +void uio_release(acc_t* acc){ + munmap((void*)acc->control_base_address, MAP_SIZE); +} + +int filter_dir(const struct dirent *entry) +{ + int i = strcmp(entry->d_name, "uio\n"); + return (i>0); +} + +int uio_initialize(const char* name, int* id){ + + char file[MAX_UIO_PATH_SIZE]; + FILE* file_ptr; + struct dirent **namelist; + int n, i, j; + + char tmp_name[MAX_UIO_NAME_SIZE]; + + if(strlen(name)>MAX_UIO_NAME_SIZE){ + printf("ERROR: uio name too long\r\n"); + return 1; + } + + n = scandir("/sys/class/uio/", &namelist, filter_dir, alphasort); + if(n <0){ + return 1; + } + + + // Get name and id of the uio devices + for (i = 0; i < n; i++) { + strcpy(file, "/sys/class/uio/"); + strcat(file, namelist[i]->d_name); + strcat(file, "/name"); + + // get name + file_ptr = fopen(file, "r"); + if(!file_ptr){ + printf("ERROR: File not existing!\n"); + return 2; + } + if (fgets(tmp_name, MAX_UIO_NAME_SIZE, file_ptr) == NULL){ + printf("ERROR: Fgets!\n"); + fclose(file_ptr); + return 3; + } + fclose(file_ptr); + + for (j=0; (*tmp_name)&&(jd_name) + 3); + printf("Found id: %d\n", *id); + break; + } + } + // Free namelist pointers which are allocated by scandir + if (namelist!= NULL){ + for (i = 0; i < n; i++) + { + free(namelist[i]); + } + free(namelist); + } + + return 0; +} + +int uio_open(int *fd, int *id){ + char file[MAX_UIO_PATH_SIZE]; + + assert(fd != NULL); + sprintf(file, "/dev/uio%d", *id); + if ((*fd = open(file, O_RDWR)) < 0) { + printf("ERROR: Could not open file: %s \n", file); + return 1; + } + else{ + return 0; + } +} + + +void uio_close(int *fd){ + assert(fd != NULL); + close(*fd); +} + +int uio_wait_interrupt(int *fd){ + assert(fd != NULL); + int int_count; + int err; + // blocking read + err = read(*fd, &int_count, sizeof(int_count)); + if(err != sizeof(int_count)){ + printf("ERROR when reading uio!"); + return 1; + } + return 0; +} + +int uio_enable_interrupt(int *fd){ + assert(fd != NULL); + int int_count = 1; + int err; + err = write(*fd, &int_count, sizeof(int_count)); + if(err != sizeof(int_count)){ + printf("Error when writing uio dev!\n"); + return 1; + } + return 0; +} + +/*************************************************************************/ \ No newline at end of file diff --git a/mtapi_plugins_c/mtapi_zynq_c/src/embb_mtapi_zynq_driver.h b/mtapi_plugins_c/mtapi_zynq_c/src/embb_mtapi_zynq_driver.h new file mode 100644 index 0000000..488dfa8 --- /dev/null +++ b/mtapi_plugins_c/mtapi_zynq_c/src/embb_mtapi_zynq_driver.h @@ -0,0 +1,117 @@ +/* + * Copyright (c) 2014-2017, Siemens AG. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * 2. 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. + * + * 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 HOLDER 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. + */ + +#ifndef EMBB_MTAPI_ZYNQ_DRIVER_H_ +#define EMBB_MTAPI_ZYNQ_DRIVER_H_ + +// welche header dateien sollten alle inkludiert werden? +// forward: nur forward im header einfügen und definition nur in c datei? + +#include +#include +#include +#include + + + +#ifdef __cplusplus +extern "C" { +#endif + +/*************************************************************************/ + +#define MAX_UIO_NAME_SIZE 64 +/* Typedefs */ + + +struct uio_info_struct{ + int uio_id; + char uio_name[MAX_UIO_NAME_SIZE]; +}; + +typedef struct uio_info_struct uio_info_t; + +struct acc_struct{ + uint32_t* control_base_address; + uint32_t phys_address; + int uio_id; + int uio_fd; + char uio_name[MAX_UIO_NAME_SIZE]; +}; + +typedef struct acc_struct acc_t; + +struct cma_buffer_struct{ + uint32_t phys_addr; + uint32_t* virt_addr; + int32_t id; + uint32_t len; // len must be dividible by 4 or 8 depending on __SIZEOF_POINTER__ + uint8_t cacheable; +}; + +typedef struct cma_buffer_struct cma_buffer_t; + +/*************************************************************************/ + + +/* Function Prototypes */ +int cma_alloc_buf(cma_buffer_t* cma_buf); +int cma_free_buf(cma_buffer_t* cma_buf); + +int acc_initialize(acc_t* acc); +int acc_release(acc_t* acc); +void acc_interrupt_global_disable(acc_t* acc); +void acc_interrupt_global_enable(acc_t* acc); +void acc_interrupt_done_enable(acc_t* acc); +void acc_interrupt_done_disable(acc_t* acc); +void acc_interrupt_clear(acc_t* acc); +uint32_t acc_interrupt_read(acc_t* acc); + + +void acc_start(acc_t* acc); +void acc_write_arguments_addr(acc_t* acc, cma_buffer_t* cma_arguments); +void acc_write_arguments_size(acc_t* acc, uint32_t arguments_size); +void acc_write_result_addr(acc_t* acc, cma_buffer_t* cma_results); +void acc_write_result_size(acc_t* acc, uint32_t result_size); +void acc_write_node_local_data_addr(acc_t* acc, cma_buffer_t* cma_node_local_data); +void acc_write_node_local_data_size(acc_t* acc, uint32_t node_local_data_size); +void acc_write_config(acc_t* acc, uint32_t reg); + +void uio_mmap(acc_t* acc); +void uio_release(acc_t* acc); +int uio_initialize(const char* name, int* id); +int uio_open(int *fd, int *id); +void uio_close(int *fd); +int uio_wait_interrupt(int *fd); +int uio_enable_interrupt(int *fd); + +/*************************************************************************/ + +#ifdef __cplusplus +} +#endif + +#endif // EMBB_MTAPI_ZYNQ_DRIVER_H_ diff --git a/mtapi_plugins_c/mtapi_zynq_c/src/embb_mtapi_zynq_task_queue.c b/mtapi_plugins_c/mtapi_zynq_c/src/embb_mtapi_zynq_task_queue.c new file mode 100644 index 0000000..8d23b32 --- /dev/null +++ b/mtapi_plugins_c/mtapi_zynq_c/src/embb_mtapi_zynq_task_queue.c @@ -0,0 +1,118 @@ +/* + * Copyright (c) 2014-2017, Siemens AG. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * 2. 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. + * + * 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 HOLDER 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 + + +/* ---- CLASS MEMBERS ------------------------------------------------------ */ + +void embb_mtapi_zynq_task_queue_initialize(embb_mtapi_zynq_task_queue_t* that) { + assert(MTAPI_NULL != that); + + that->front = MTAPI_NULL; + that->back = MTAPI_NULL; + mtapi_queueattr_init(&that->attributes, MTAPI_NULL); + embb_spin_init(&that->lock); +} + +void embb_mtapi_zynq_task_queue_finalize(embb_mtapi_zynq_task_queue_t* that) { + that->front = MTAPI_NULL; + that->back = MTAPI_NULL; + embb_spin_destroy(&that->lock); +} + +embb_mtapi_zynq_task_t * embb_mtapi_zynq_task_queue_pop_front( + embb_mtapi_zynq_task_queue_t* that) { + embb_mtapi_zynq_task_t * task = MTAPI_NULL; + + assert(MTAPI_NULL != that); + + if (embb_spin_try_lock(&that->lock, 128) == EMBB_SUCCESS) { + if (MTAPI_NULL != that->front) { + task = that->front; + if (that->front == that->back) { + that->front = MTAPI_NULL; + that->back = MTAPI_NULL; + } else { + that->front = task->next; + } + } + embb_spin_unlock(&that->lock); + } + + return task; +} + +mtapi_boolean_t embb_mtapi_zynq_task_queue_push_back( + embb_mtapi_zynq_task_queue_t* that, + embb_mtapi_zynq_task_t * task) { + mtapi_boolean_t result = MTAPI_FALSE; + + assert(MTAPI_NULL != that); + + if (embb_spin_lock(&that->lock) == EMBB_SUCCESS) { + task->next = MTAPI_NULL; + if (MTAPI_NULL == that->front) { + that->front = task; + } else { + that->back->next = task; + } + that->back = task; + result = MTAPI_TRUE; + embb_spin_unlock(&that->lock); + } + + return result; +} + +mtapi_boolean_t embb_mtapi_zynq_task_queue_push_front( + embb_mtapi_zynq_task_queue_t* that, + embb_mtapi_zynq_task_t * task) { + mtapi_boolean_t result = MTAPI_FALSE; + + assert(MTAPI_NULL != that); + + if (embb_spin_lock(&that->lock) == EMBB_SUCCESS) { + task->next = that->front; + if (MTAPI_NULL == that->front) { + that->back = task; + } + that->front = task; + result = MTAPI_TRUE; + embb_spin_unlock(&that->lock); + } + + return result; +} diff --git a/mtapi_plugins_c/mtapi_zynq_c/src/embb_mtapi_zynq_task_queue.h b/mtapi_plugins_c/mtapi_zynq_c/src/embb_mtapi_zynq_task_queue.h new file mode 100644 index 0000000..b2ec167 --- /dev/null +++ b/mtapi_plugins_c/mtapi_zynq_c/src/embb_mtapi_zynq_task_queue.h @@ -0,0 +1,104 @@ +/* + * Copyright (c) 2014-2017, Siemens AG. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * 2. 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. + * + * 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 HOLDER 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. + */ + +#ifndef EMBB_MTAPI_ZYNQ_TASK_QUEUE_T_H_ +#define EMBB_MTAPI_ZYNQ_TASK_QUEUE_T_H_ + +#include +#include + +#include + +#ifdef __cplusplus +extern "C" { +#endif + +/* ---- FORWARD DECLARATIONS ----------------------------------------------- */ + +#include + + +/* ---- CLASS DECLARATION -------------------------------------------------- */ + +/** + * \internal + * Task queue class. + * + * \ingroup INTERNAL + */ +struct embb_mtapi_zynq_task_queue_struct { + embb_mtapi_zynq_task_t * front; + embb_mtapi_zynq_task_t * back; + mtapi_queue_attributes_t attributes; + embb_spinlock_t lock; +}; + +#include + +/** + * Default constructor. + * \memberof embb_mtapi_zynq_task_queue_struct + */ +void embb_mtapi_zynq_task_queue_initialize(embb_mtapi_zynq_task_queue_t* that); + +/** + * Destructor. + * \memberof embb_mtapi_zynq_task_queue_struct + */ +void embb_mtapi_zynq_task_queue_finalize(embb_mtapi_zynq_task_queue_t* that); + +/** + * Pop a task from the front of the queue. Returns MTAPI_NULL if the queue is + * empty. + * \memberof embb_mtapi_zynq_task_queue_struct + */ +embb_mtapi_zynq_task_t * embb_mtapi_zynq_task_queue_pop_front( + embb_mtapi_zynq_task_queue_t* that); + +/** + * Push a task to the back of the queue. Returns MTAPI_TRUE if successfull and + * MTAPI_FALSE if the queue is full or cannot be locked in time. + * \memberof embb_mtapi_zynq_task_queue_struct + */ +mtapi_boolean_t embb_mtapi_zynq_task_queue_push_back( + embb_mtapi_zynq_task_queue_t* that, + embb_mtapi_zynq_task_t * task); + +/** + * Push a task to the front of the queue. Returns MTAPI_TRUE if successfull and + * MTAPI_FALSE if the queue is full or cannot be locked in time. + * \memberof embb_mtapi_zynq_task_queue_struct + */ +mtapi_boolean_t embb_mtapi_zynq_task_queue_push_front( + embb_mtapi_zynq_task_queue_t* that, + embb_mtapi_zynq_task_t * task); + + +#ifdef __cplusplus +} +#endif + +#endif // EMBB_MTAPI_ZYNQ_TASK_QUEUE_T_H_ diff --git a/mtapi_plugins_c/mtapi_zynq_c/src/embb_mtapi_zynq_task_queue_t_fwd.h b/mtapi_plugins_c/mtapi_zynq_c/src/embb_mtapi_zynq_task_queue_t_fwd.h new file mode 100644 index 0000000..9e5d97d --- /dev/null +++ b/mtapi_plugins_c/mtapi_zynq_c/src/embb_mtapi_zynq_task_queue_t_fwd.h @@ -0,0 +1,44 @@ +/* + * Copyright (c) 2014-2017, Siemens AG. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * 2. 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. + * + * 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 HOLDER 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. + */ + +#ifndef EMBB_MTAPI_ZYNQ_TASK_QUEUE_T_FWD_H_ +#define EMBB_MTAPI_ZYNQ_TASK_QUEUE_T_FWD_H_ + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * Task queue type. + * \memberof embb_mtapi_zynq_task_queue_struct + */ +typedef struct embb_mtapi_zynq_task_queue_struct embb_mtapi_zynq_task_queue_t; + +#ifdef __cplusplus +} +#endif + +#endif // EMBB_MTAPI_ZYNQ_TASK_QUEUE_T_FWD_H_ diff --git a/mtapi_plugins_c/mtapi_zynq_c/src/embb_mtapi_zynq_task_t_fwd.h b/mtapi_plugins_c/mtapi_zynq_c/src/embb_mtapi_zynq_task_t_fwd.h new file mode 100644 index 0000000..cab8af8 --- /dev/null +++ b/mtapi_plugins_c/mtapi_zynq_c/src/embb_mtapi_zynq_task_t_fwd.h @@ -0,0 +1,44 @@ +/* + * Copyright (c) 2014-2017, Siemens AG. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * 2. 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. + * + * 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 HOLDER 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. + */ + +#ifndef EMBB_MTAPI_ZYNQ_TASK_T_FWD_H_ +#define EMBB_MTAPI_ZYNQ_TASK_T_FWD_H_ + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * Task type. + * \memberof embb_mtapi_task_pl_struct + */ +typedef struct embb_mtapi_zynq_task_struct embb_mtapi_zynq_task_t; + +#ifdef __cplusplus +} +#endif + +#endif // EMBB_MTAPI_ZYNQ_TASK_T_FWD_H_ \ No newline at end of file diff --git a/mtapi_plugins_c/mtapi_zynq_c/src/embb_mtapi_zynq_xlnk_ioctl.h b/mtapi_plugins_c/mtapi_zynq_c/src/embb_mtapi_zynq_xlnk_ioctl.h new file mode 100644 index 0000000..384a6ab --- /dev/null +++ b/mtapi_plugins_c/mtapi_zynq_c/src/embb_mtapi_zynq_xlnk_ioctl.h @@ -0,0 +1,117 @@ +#ifndef EMBB_MTAPI_ZYNQ_XLNK_IOCTL_H_ +#define EMBB_MTAPI_ZYNQ_XLNK_IOCTL_H_ + +#include +#include + +#define ALLOCATE_CMA_BUFFER _IOWR('X', 2, unsigned long) +#define FREE_CMA_BUFFER _IOWR('X', 3, unsigned long) + +#if __SIZEOF_POINTER__ == 4 + typedef uint32_t ptr_type; +#elif __SIZEOF_POINTER__ == 8 + typedef uint64_t ptr_type; +#else + #error +#endif + +union xlnk_arguments_u { + struct __attribute__ ((__packed__)) { + uint32_t len; + int32_t id; + ptr_type phys_addr; + uint8_t cacheable; + } allocate_buffer; + struct __attribute__ ((__packed__)) { + uint32_t id; + ptr_type buffer; + } free_buffer; + struct __attribute__ ((__packed__)) { + int32_t unused_0; + ptr_type unused_1; + } unused_struct_0; + struct __attribute__ ((__packed__)) { + int8_t unused_0[64]; + ptr_type unused_1; + uint32_t unused_2; + uint32_t unused_3; + } unused_struct_1; + struct __attribute__ ((__packed__)) { + ptr_type unused_0; + ptr_type unused_1; + ptr_type unused_2; + uint32_t unused_3; + uint32_t unused_4; + uint32_t unused_5; + ptr_type unused_6; + uint32_t unused_7; + int32_t unused_8; + uint32_t unused_9; + uint32_t unused_10[5]; + uint32_t unused_11; + uint32_t unused_12; + ptr_type unused_13; + uint32_t unused_14; + } unused_struct_2; + struct __attribute__ ((__packed__)) { + ptr_type unused_0; + uint32_t unused_1; + uint32_t unused_2[5]; + uint32_t unused_3; + } unused_struct_3; + struct __attribute__ ((__packed__)) { + ptr_type unused_0; + } unused_struct_4; + struct __attribute__ ((__packed__)) { + ptr_type unused_0; + uint32_t unused_1; + uint32_t unused_2[8]; + int8_t unused_3[32]; + uint32_t unused_4; + } unused_struct_5; + struct __attribute__ ((__packed__)) { + ptr_type unused_0; + } unused_struct_6; + struct __attribute__ ((__packed__)) { + int8_t unused_0[32]; + uint32_t unused_1; + ptr_type unused_2; + uint32_t unused_3; + uint32_t unused_4; + uint32_t unused_5; + uint32_t unused_6; + uint32_t unused_7; + uint32_t unused_8; + uint32_t unused_9; + uint32_t unused_10; + uint32_t unused_11; + uint32_t unused_12; + uint32_t unused_13; + uint32_t unused_14; + } unused_struct_7; + struct __attribute__ ((__packed__)) { + int8_t unused_0[32]; + uint32_t unused_1; + ptr_type unused_2; + uint32_t unused_3; + uint32_t unused_4; + uint32_t unused_5; + uint32_t unused_6; + uint32_t unused_7; + } unused_struct_8; + struct __attribute__ ((__packed__)) { + ptr_type unused_0; + uint32_t unused_1; + int32_t unused_2; + } unused_struct_9; + struct __attribute__ ((__packed__)) { + ptr_type unused_0; + int32_t unused_1; + int32_t unused_2; + int32_t unused_3; + ptr_type unused_4; + ptr_type unused_5; + } unused_struct_10; +}; + +#endif // EMBB_MTAPI_ZYNQ_XLNK_IOCTL_H_ \ No newline at end of file diff --git a/mtapi_plugins_c/mtapi_zynq_c/src/exports.def b/mtapi_plugins_c/mtapi_zynq_c/src/exports.def new file mode 100644 index 0000000..bc4a4c6 --- /dev/null +++ b/mtapi_plugins_c/mtapi_zynq_c/src/exports.def @@ -0,0 +1,5 @@ +LIBRARY embb_mtapi_pl_c +EXPORTS +mtapi_pl_plugin_initialize +mtapi_pl_plugin_finalize +mtapi_pl_action_create diff --git a/mtapi_plugins_c/mtapi_zynq_c/test/embb_mtapi_zynq_test_task.cc b/mtapi_plugins_c/mtapi_zynq_c/test/embb_mtapi_zynq_test_task.cc new file mode 100644 index 0000000..5975430 --- /dev/null +++ b/mtapi_plugins_c/mtapi_zynq_c/test/embb_mtapi_zynq_test_task.cc @@ -0,0 +1,150 @@ +/* + * Copyright (c) 2014-2017, Siemens AG. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * 2. 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. + * + * 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 HOLDER 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 + +#define MTAPI_CHECK_STATUS(status) \ +PT_ASSERT(MTAPI_SUCCESS == status) + +#define ZYNQ_DOMAIN 1 +#define ZYNQ_NODE 2 +#define ZYNQ_JOB 2 + +//debugging +#include + +TaskTest::TaskTest() { + CreateUnit("mtapi zynq task test").Add(&TaskTest::TestBasic, this); +} + +void TaskTest::TestBasic() { + mtapi_status_t status; + mtapi_job_hndl_t job; + mtapi_task_hndl_t task; + mtapi_action_hndl_t action; + + uint32_t arguments[2]; + uint32_t result_buffer[1]; + uint32_t node_local_data[1]; + + arguments[0] = 1; + arguments[1] = 2; + node_local_data[0] = 3; + result_buffer[0] = 0; + + char name[9] = "UIO_test"; + std::cout << "Plugin initialize" << std::endl; + mtapi_zynq_plugin_initialize(name, &status); + if (status == MTAPI_ERR_FUNC_NOT_IMPLEMENTED) { + // Zynq unavailable + return; + } + MTAPI_CHECK_STATUS(status); + + mtapi_initialize( + ZYNQ_DOMAIN, + ZYNQ_NODE, + MTAPI_NULL, + MTAPI_NULL, + &status); + MTAPI_CHECK_STATUS(status); + + + // Use /dev/mem for memory mapping + action = mtapi_zynq_action_create( + ZYNQ_JOB, + MTAPI_NULL, + 0xa0010000, + node_local_data, 1 *sizeof(uint32_t), + 0, + &status); + MTAPI_CHECK_STATUS(status); + + status = MTAPI_ERR_UNKNOWN; + job = mtapi_job_get(ZYNQ_JOB, ZYNQ_DOMAIN, &status); + MTAPI_CHECK_STATUS(status); + + task = mtapi_task_start( + MTAPI_TASK_ID_NONE, + job, + arguments, 2 * sizeof(uint32_t), + result_buffer, 1 *sizeof(uint32_t), + MTAPI_DEFAULT_TASK_ATTRIBUTES, + MTAPI_GROUP_NONE, + &status); + MTAPI_CHECK_STATUS(status); + + mtapi_task_wait(task, MTAPI_INFINITE, &status); + MTAPI_CHECK_STATUS(status); + + PT_EXPECT_EQ(result_buffer[0], (uint32_t) 6); + std::cout << "Result: " << result_buffer[0] << std::endl; + + mtapi_action_delete(action, MTAPI_INFINITE, &status); + MTAPI_CHECK_STATUS(status); + + + // Use UIO for memory mapping + action = mtapi_zynq_action_create( + ZYNQ_JOB, + name, + 0, + node_local_data, 1 *sizeof(uint32_t), + 0, + &status); + MTAPI_CHECK_STATUS(status); + + status = MTAPI_ERR_UNKNOWN; + job = mtapi_job_get(ZYNQ_JOB, ZYNQ_DOMAIN, &status); + MTAPI_CHECK_STATUS(status); + + task = mtapi_task_start( + MTAPI_TASK_ID_NONE, + job, + arguments, 2 * sizeof(uint32_t), + result_buffer, 1 *sizeof(uint32_t), + MTAPI_DEFAULT_TASK_ATTRIBUTES, + MTAPI_GROUP_NONE, + &status); + MTAPI_CHECK_STATUS(status); + + mtapi_task_wait(task, MTAPI_INFINITE, &status); + MTAPI_CHECK_STATUS(status); + + PT_EXPECT_EQ(result_buffer[0], (uint32_t) 6); + std::cout << "Result: " << result_buffer[0] << std::endl; + + mtapi_action_delete(action, MTAPI_INFINITE, &status); + MTAPI_CHECK_STATUS(status); + + mtapi_zynq_plugin_finalize(&status); + MTAPI_CHECK_STATUS(status); + + mtapi_finalize(&status); + MTAPI_CHECK_STATUS(status); +} diff --git a/mtapi_plugins_c/mtapi_zynq_c/test/embb_mtapi_zynq_test_task.h b/mtapi_plugins_c/mtapi_zynq_c/test/embb_mtapi_zynq_test_task.h new file mode 100644 index 0000000..fbabd88 --- /dev/null +++ b/mtapi_plugins_c/mtapi_zynq_c/test/embb_mtapi_zynq_test_task.h @@ -0,0 +1,40 @@ +/* + * Copyright (c) 2014-2017, Siemens AG. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * 2. 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. + * + * 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 HOLDER 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. + */ + +#ifndef MTAPI_PLUGINS_C_MTAPI_ZYNQ_C_TEST_EMBB_MTAPI_ZYNQ_TEST_TASK_H_ +#define MTAPI_PLUGINS_C_MTAPI_ZYNQ_C_TEST_EMBB_MTAPI_ZYNQ_TEST_TASK_H_ + +#include + +class TaskTest : public partest::TestCase { + public: + TaskTest(); + + private: + void TestBasic(); +}; + +#endif // MTAPI_PLUGINS_C_MTAPI_ZYNQ_C_TEST_EMBB_MTAPI_ZYNQ_TEST_TASK_H_ diff --git a/mtapi_plugins_c/mtapi_zynq_c/test/main.cc b/mtapi_plugins_c/mtapi_zynq_c/test/main.cc new file mode 100644 index 0000000..1457d94 --- /dev/null +++ b/mtapi_plugins_c/mtapi_zynq_c/test/main.cc @@ -0,0 +1,35 @@ +/* + * Copyright (c) 2014-2017, Siemens AG. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * 2. 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. + * + * 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 HOLDER 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 + +PT_MAIN("MTAPI ZYNQ") { + PT_RUN(TaskTest); +}