pax_global_header00006660000000000000000000000064144667715200014526gustar00rootroot0000000000000052 comment=4dbd33accb043bd92ecbec2a3507f85a22045c51 dfx-mgr-xilinx_v2023.2/000077500000000000000000000000001446677152000147435ustar00rootroot00000000000000dfx-mgr-xilinx_v2023.2/.gitignore000066400000000000000000000002071446677152000167320ustar00rootroot00000000000000build*/ *.o *.bin *.map *.out *.log *.swp *.swo *.d CMakeFiles/ CMakeCache.txt /tags /TAGS # cscope files cscope.* ncscope.* *.*~ *~ dfx-mgr-xilinx_v2023.2/.gitmodules000066400000000000000000000003641446677152000171230ustar00rootroot00000000000000[submodule "example/aes128"] path = example/aes128 url = https://gitenterprise.xilinx.com/SET-HW/aesdemo.git [submodule "example/sihaExamples"] path = example/sihaExamples url = https://gitenterprise.xilinx.com/SET-HW/sihaAcapdExamples.git dfx-mgr-xilinx_v2023.2/CMakeLists.txt000066400000000000000000000026171446677152000175110ustar00rootroot00000000000000######################################################################### # Copyright (c) 2021, Xilinx Inc. and Contributors. All rights reserved. # SPDX-License-Identifier: MIT ######################################################################### cmake_minimum_required (VERSION 2.6) if (POLICY CMP0048) cmake_policy(SET CMP0048 NEW) endif() list (APPEND CMAKE_MODULE_PATH "${CMAKE_CURRENT_SOURCE_DIR}/cmake" "${CMAKE_CURRENT_SOURCE_DIR}/cmake/platforms") project (dfx-mgr C ASM) include (CheckIncludeFiles) include (CheckCSourceCompiles) include (collect) include (options) include_directories(include) foreach(_inc_path ${CMAKE_INCLUDE_PATH}) collect (PROJECT_INC_DIRS "${_inc_path}") endforeach() foreach (_lib ${_deps}) message ("Looking for ${_lib}") find_library (_lib_path ${_lib}) if (NOT _lib_path) message ( "external library ${_lib} not found" ) message ( "hint: you may need to pass -DCMAKE_LIBRARY_PATH=" ) message ( FATAL_ERROR "library ${_lib} is required to build the examples" ) endif (NOT _lib_path) get_filename_component (_lib_dir_path ${_lib_path} DIRECTORY) collect (PROJECT_LIB_DIRS ${_lib_dir_path}) unset(_lib_path CACHE) endforeach() collector_list (_list PROJECT_LIB_DIRS) link_directories (${_list}) add_subdirectory (src) add_subdirectory (example) #if (WITH_EXAMPLE) #endif (WITH_EXAMPLE) # vim: expandtab:ts=2:sw=2:smartindent dfx-mgr-xilinx_v2023.2/LICENSE000066400000000000000000000026271446677152000157570ustar00rootroot00000000000000MIT License Copyright (c) 2021, Xilinx Inc. and Contributors. Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. --------------------------------------------------------------------------- Note: Use the following tag instead of the full license text in the individual files: SPDX-License-Identifier: MIT This enables machine processing of license information based on the SPDX License Identifiers that are here available: http://spdx.org/licenses/ dfx-mgr-xilinx_v2023.2/Linux-Bringup-README.md000066400000000000000000000056601446677152000207320ustar00rootroot00000000000000 # Default Images Location: /group/siv3/staff/acapd/default_images/ ``` ├── arm-trusted-firmware.elf # ARM trusted firmware ├── bzip2-system-nopl.dtb # Linux bringup DTB ├── system-bzip2-smmu.dtb # Linux bringup DTB for bzip2 with SMMU ├── bzip2.tcl # example TCL to bringup Linux ├── bzip_accel_eve_wrapper.pdi # Bzip2 hardware PDI ├── Image # Default Linux image ├── rootfs.cpio # Base rootfs cpio └── rootfs.cpio.ub # base Rootfs with u-boot wrapper ``` # How to launch the images TCL Example: /group/siv3/staff/acapd/default_images/bzip2.tcl Steps: * Launch a command line console for the interaction with the target Linux ``` $ systest tenzing # Wait until you get a board # Setup tftpd directory to load images from u-boot Systest# tftpd "" # Connect to console Systest# connect com0 ``` * Launch another command linux console to use xsdb with systest: ``` $ ssh > /opt/systest/common/bin/systest-client Systest # xsdb xsdb% connect xsdb% targets -set -filter {name =~ "Versal*"} xsdb% device program xsdb% targets -set -filter {name =~ "Cortex-A72 #0*" } xsdb% rst -proc xsdb% dow -force -data 0x1000 xsdb% dow -force u-boot.elf xsdb% dow -force arm-trusted-firmware.elf xsdb% con ``` * On the other console, when you see u-boot boots, tftp boot the Linux images: ``` # If Image doesn't include rootfs: Versal> dhcp; setenv serverip 10.10.70.101; tftpb 80000 Image; tftpb 10000000 rootfs.cpio.ub; tftpb 14000000 system.dtb; booti 80000 10000000 14000000 # If Image includes rootfs: Versal> dhcp; setenv serverip 10.10.70.101; tftpb 80000 Image;tftpb 14000000 system.dtb; booti 80000 - 14000000 ``` # Repackage Rootfs ``` #Extract rootfs.cpio(do all operations with sudo access) mkdir tmprootfs cd tmprootfs sudo cpio -idv < ../rootfs.cpio #Make changes as per your requiredments #Pack rootfs sudo find . | cpio --create --format='newc' > ../rootfs.cpio Rebuild Linux image with the new Rootfs CPIO #On bash setup env before starting compilation stepsexport ARCH=arm64 export CROSS_COMPILE=aarch64-linux-gnu- source /proj/xbuilds/2019.2_daily_latest/installs/lin64/Scout/2019.2/settings64.sh # Forking the Linux repo failed, for now use this tested commit: 724da59eee2f2b9b7172116c9729ea8a38d2d3c4 git clone https://gitenterprise.xilinx.com/linux/linux-xlnx.git -b master-next-test git checkout 724da59eee2f2b9b7172116c9729ea8a38d2d3c4 #For Versal make ARCH=arm64 xilinx_versal_defconfig make ARCH=arm64 menuconfig #Point to your arm64 rootfs cpio image generated in previous step CONFIG_INITRAMFS_SOURCE="" #Enable the following options: CONFIG_INITRAMFS_SOURCE="" CONFIG_FPGA=y CONFIG_FPGA_MGR_VERSAL_FPGA=y # Build Linux Image make ARCH=arm64 -j # Image will be in arch/arm64/boot/Image ``` # Components Repo * Linux kernel: * repo: git@gitenterprise.xilinx.com:Madagascar/linux-xlnx.git * branch: acapd/master-next-test dfx-mgr-xilinx_v2023.2/README.md000066400000000000000000000376451446677152000162410ustar00rootroot00000000000000#### Copyright (c) 2021, Xilinx Inc. and Contributors. All rights reserved. #### SPDX-License-Identifier: MIT ## Overview DFX-MGR provides infrastructure to abstract configuration and hardware resource management for dynamic deployment of Xilinx based accelerator across different platforms. DFX-MGR is merged in Petalinux 2021.1 onwards and the recipe is called `dfx-mgr`. The recipe is not enabled by default and user is expected to enable it. As of today, DFX-MGR can be used for dynamic loading/unloading of accelerators to PL (Programmable Logic). The functionality is tested for loading/unloading of Flat shell (i.e. shell which does not have any reconfigurable partitions) and DFX shell (i.e. shell which contains static and dynamic region). As you can see in the diagram below DFX-MGR can load a 3RP design and a 2RP design with the corresponding accelerators dynamically without having to reboot the board. Once you compile Petalinux by enabling the dfx-mgr recipe, you should have dfx-mgrd and dfx-mgr-client in `/usr/bin` of rootfs and libdfx-mgr.so in `/usr/lib`. The config file `daemon.conf` can be found in `/etc/dfx-mgrd/`. Config file is mandatory, refer the files section for details of it. A default daemon.conf will be copied by the recipe and the user is expected to update as required. ![Screenshot](https://media.gitenterprise.xilinx.com/user/978/files/c2254180-9d53-11eb-9371-ad2d44922a8b) ## Files required DFX-MGR recognizes the designs under `/lib/firmware/xilinx` on device filesystem, location can be updated in `daemon.conf`. Designs could be downloaded using dnf or any other package manager or manually copied to the previously mentioned location. Each folder under `/lib/firmware/xilinx` will be treated as a base shell design wherein the folder is expected to have a shell.json file. Base design folder can then have sub-folder for each of the accelerators. Each accelerator is expected to have a accel.json. Have a look at below folder structure for more understanding and the details of json config files. The expected directory structure under `/lib/firmware/xilinx` which contains a 3x1 PL shell design, and a flat shell design. 3x1 `base_design` shell has an accelerator called FFT which contains three different partial bitstreams for three slots of base shell. `base_design` needs to have base shell bitstream and shell.json. DFX-MGR expects '_slot#' as subfolders for each of the accelerators for DFX designs. Place the bitstream corresponding to that slot in the respective subfolder along with accel.json file. It is not mandatory to have all the partial bitstreams for each slot, but DFX-MGR will fail to load an accelerator to the slot if no partial design is found. ``` $ ls /lib/firmware/xilinx/base_design base_Shell.pdi base.dtbo shell.json FFT $ ls /lib/firmware/xilinx/base_design/FFT/ FFT_slot0 FFT_slot1 FFT_slot2 $ ls /lib/firmware/xilinx/base_design/FFT/FFT_slot0/ partial.pdi partial.dtbo accel.json $ ls /lib/firmware/xilinx/base_design/FFT/FFT_slot1/ partial.pdi partial.dtbo accel.json $ ls /lib/firmware/xilinx/base_design/FFT/FFT_slot2/ partial_slot2.pdi partial.dtbo accel.json $ ls /lib/firmware/xilinx/flat_shell/ Flat_shell.bit.bin flat_shell.dtbo shell.json ``` As shown above, base_design has first three slots (0,1,2) corresponding to PL slots from the FFT subfolders. When DFX-MGR successfully loads FFT accel to one of the slots, -listPackage output would show active slot as 0,1 or 2. ### daemon.conf DFX-MGR is started on Linux bootup and reads the config file `/etc/dfx-mgrd/daemon.conf` from device for any config settings. Any change to daemon.conf will need a restart of the /usr/bin/dfx-mgrd on target. If you want to add another location for packages on the filesystem, append absolute path to the location in "firmware_location" and restart the daemon. The limitations around directory structure as explained above still apply as for "/lib/firmware/xilinx". ``` $ cat /etc/dfx-mgrd/daemon.conf { "default_accel":"/etc/dfx-mgrd/default_firmware", //Optional: echo the //package-name to default_firmware for any // accelerator to be loaded on start of daemon "firmware_location": ["/lib/firmware/xilinx"] //Required:Package directories // monitored by DFX-MGR } ``` ### shell.json shell.json describes the base shell configuration information. Optional fields can be skipped if not desired. One of the below type should be used for shell_type as per your design. * XRT_FLAT: dfx-mgr will program the PL and update /etc/vart.conf on target with the path to the active xclbin on success. * PL_FLAT: dfx-mgr will program the PL bitstream and treat the design as static. * PL_DFX: dfx-mgr will treat the design as DFX with number of slots as mentioned in json. ``` $ cat shell.json { "shell_type" : "PL_DFX",// Required: valid values are XRT_FLAT/PL_FLAT/PL_DFX "num_pl_slots": 3, //Required: Number of pl slots in your base shell design "num_aie_slots":1, //Required: Number of aie slots in your base shell design "load_base_design": "no" //Optional : If the shell was loaded during boot //and you want to skip loading base shell when loading the // accelerators to the slot. "device_name" : "a0010000.SIHA_Manager", //optional: IP name "reg_base" : "", //Optional: IP device base address "reg_size" : "", //Optional "clock_device_name" : "a0000000.clk_wiz", //optional "clock_reg_base" : "",//optional "clock_reg_size" : "", //optional "isolation_slots": [ // optional, specify the register offsets and the corresponding values to be // written for each slot to bring it out of isolation, expects the length //of array equal to number of slots { "offset": ["0x4000","0x4004","0x4008","0x400c"],//Address offset for first slot "values": ["0x01","0x01", "0x0b", "0x02"] }, //Value to be written to above regs { "offset": ["0x5000","0x5004","0x5008","0x500c"], "values": ["0x01","0x01", "0x0b", "0x02"]}, { "offset": ["0x6000","0x6004","0x6008","0x600c"], "values": ["0x01","0x01","0x0b", "0x02"] }] } ``` > **Note:** The [AIE](https://www.xilinx.com/products/technology/ai-engine.html) > support in dfx-mgr is preliminary and for a future production enablement capability. > [KRIA](https://www.xilinx.com/products/som/kria.html) devices do not have AIE. ### accel.json accel.json describes the accelerator configuration. Optional fields can be skipped if not desired. Flat shell designs are not required to have accel.json since they do not have reconfigurable partition. * SIHA_PL_DFX: Use this option for PL accelerators build with [SIHA manager](https://github.com/Xilinx/kria-dfx-hw/tree/xlnx_rel_v2022.1/k26/ip_repo/siha_manager), this enables some extra steps required to bring the slots out of isolation in addition to programming the bitstream. * XRT_PL_DFX: Use this option for XRT based PL accelerator. ``` $ cat accel.json { "accel_type": "", // Required: supported types are SIHA_PL_DFX / XRT_PL_DFX "accel_devices":[ // Optional: list of IP devices corresponding to this slot design { "dev_name": "20100000000.accel", "reg_base":"", "reg_size":"" }], "sharedMemoryConfig": { "sizeInKB": "", "sharedMemType" : ""}, "dataMoverConfig": { // Optional: skip this if application handles its own dma "dma_dev_name":"a4000000.dma", "dma_driver":"vfio-platform", "dma_reg_base":"", "dma_reg_size":"", "iommu_group":"0", "Bus": "platform", "HWType": "mcdma", "max_buf_size":"8388608", "dataMoverCacheCoherent": "Yes", "dataMoverVirtualAddress": "Yes", "dataMoverChnls":[ {"chnl_id": 0, "chnl_dir":"ACAPD_DMA_DEV_W" }, { "chnl_id": 0, "chnl_dir": "ACAPD_DMA_DEV_R" }] }, "AccelHandshakeType": "", "fallbackBehaviour": "software" // Optional: If hw accelerator fails to load, //DFX-MGR will try software fallback } ``` ## How to build DFX-MGR depends on external libraries/frameworks such as [libdfx](https://github.com/Xilinx/libdfx), [XRT](https://github.com/Xilinx/XRT), [inotify](https://en.wikipedia.org/wiki/Inotify), etc. The recommended way to compile this repo is using yocto where the required dependency are taken care of in the recipe. If not using yocto then dependent libraries will need to be provided to cmake using appropriate -DCMAKE_LIBRARY_PATH. ### How to build using yocto To compile using yocto in 2021.1 onwards, do `bitbake dfx-mgr`. ### How to build using cmake You would need to provide dependency libraries using -DCMAKE_LIBRARY_PATH for cmake. There is generic cmake toolchian file for generic Linux which is in `cmake/platforms/cross-linux-gcc.cmake` Set the path where you have all the dependent libraries in build.sh. ``` $ cd dfx-mgr $ mkdir build $ cd build $ ../build.sh ``` After build successfully completes, libdfx-mgr.so can be found under `build/usr/local/lib` and binary under `build/usr/local/bin`. ## Usage guidelines ### Using command line The dfx-mgrd daemon should mostly be running on linux startup. Assuming it is running, you can use below commands from command line to load/unload accelerators. 1. Command to list the packages present on target filesystem under `/lib/firmware/xilinx`. An alternative command line utility which some users might be familiar with can also be used `xmutil listapps`. ``` $ dfx-mgr-client -listPackage Accelerator Accel_type Base Base_type #slots(PL+AIE) Active_slot flat_shell PL_FLAT flat_shell PL_FLAT (0+0) -1 AIE_accel XRT_AIE_DFX base_design PL_DFX (3+1) 3, FFT SIHA_PL_DFX base_design PL_DFX (3+1) 0,1 ``` In the above output, AIE_accel is currently programmed to AIE and hence the slot shows as 3. FFT is programmed to first two slots out of three slots of PL. flat_shell is not programmed and show -1. Flat shell design do not have a dynamic reconfigurable partition and hence #slots shows as 0. Here is an example of 2-partition designs (see: [kria-dfx-hw](https://github.com/Xilinx/kria-dfx-hw), [kria-apps-firmware](https://github.com/Xilinx/kria-apps-firmware)) from KR260 board with Ubuntu 22.04:
``` $ tree /lib/firmware/xilinx /lib/firmware/xilinx |-- k26-starter-kits | |-- k26_starter_kits.bit.bin | |-- k26_starter_kits.dtbo | `-- shell.json |-- k26_2rp_1409 | |-- AES128 | | |-- AES128_slot0 | | | |-- accel.json | | | |-- opendfx_shell_i_RP_0_AES128_inst_0_partial.bit.bin | | | |-- opendfx_shell_i_RP_0_AES128_inst_0_partial.bit.bin_i.dtbo | | | `-- opendfx_shell_i_RP_0_AES128_inst_0_partial.bit.bin_i.dtsi | | `-- AES128_slot1 | | |-- accel.json | | |-- opendfx_shell_i_RP_1_AES128_inst_1_partial.bit.bin | | |-- opendfx_shell_i_RP_1_AES128_inst_1_partial.bit.bin_i.dtbo | | `-- opendfx_shell_i_RP_1_AES128_inst_1_partial.bit.bin_i.dtsi | |-- AES192 | | |-- AES192_slot0 | | | |-- accel.json | | | |-- opendfx_shell_i_RP_0_AES192_inst_0_partial.bit.bin | | | |-- opendfx_shell_i_RP_0_AES192_inst_0_partial.bit.bin_i.dtbo | | | `-- opendfx_shell_i_RP_0_AES192_inst_0_partial.bit.bin_i.dtsi | | `-- AES192_slot1 | | |-- accel.json | | |-- opendfx_shell_i_RP_1_AES192_inst_1_partial.bit.bin | | |-- opendfx_shell_i_RP_1_AES192_inst_1_partial.bit.bin_i.dtbo | | `-- opendfx_shell_i_RP_1_AES192_inst_1_partial.bit.bin_i.dtsi | |-- DPU | | |-- DPU_slot0 | | | |-- accel.json | | | |-- opendfx_shell_i_RP_0_DPU_512_inst_0_partial.bit.bin | | | |-- opendfx_shell_i_RP_0_DPU_512_inst_0_partial.bit.bin_i.dtbo | | | `-- opendfx_shell_i_RP_0_DPU_512_inst_0_partial.bit.bin_i.dtsi | | `-- DPU_slot1 | | |-- accel.json | | |-- opendfx_shell_i_RP_1_DPU_512_inst_1_partial.bit.bin | | |-- opendfx_shell_i_RP_1_DPU_512_inst_1_partial.bit.bin_i.dtbo | | `-- opendfx_shell_i_RP_1_DPU_512_inst_1_partial.bit.bin_i.dtsi | |-- FFT | | |-- FFT_slot0 | | | |-- accel.json | | | |-- opendfx_shell_i_RP_0_FFT_4channel_inst_0_partial.bit.bin | | | |-- opendfx_shell_i_RP_0_FFT_4channel_inst_0_partial.bit.bin_i.dtbo | | | `-- opendfx_shell_i_RP_0_FFT_4channel_inst_0_partial.bit.bin_i.dtsi | | `-- FFT_slot1 | | |-- accel.json | | |-- opendfx_shell_i_RP_1_FFT_4channel_inst_1_partial.bit.bin | | |-- opendfx_shell_i_RP_1_FFT_4channel_inst_1_partial.bit.bin_i.dtbo | | `-- opendfx_shell_i_RP_1_FFT_4channel_inst_1_partial.bit.bin_i.dtsi | |-- FIR | | |-- FIR_slot0 | | | |-- accel.json | | | |-- opendfx_shell_i_RP_0_FIR_compiler_inst_0_partial.bit.bin | | | |-- opendfx_shell_i_RP_0_FIR_compiler_inst_0_partial.bit.bin_i.dtbo | | | `-- opendfx_shell_i_RP_0_FIR_compiler_inst_0_partial.bit.bin_i.dtsi | | `-- FIR_slot1 | | |-- accel.json | | |-- opendfx_shell_i_RP_1_FIR_compiler_inst_1_partial.bit.bin | | |-- opendfx_shell_i_RP_1_FIR_compiler_inst_1_partial.bit.bin_i.dtbo | | `-- opendfx_shell_i_RP_1_FIR_compiler_inst_1_partial.bit.bin_i.dtsi | |-- PP_PIPELINE | | |-- PP_PIPELINE_slot0 | | | |-- accel.json | | | |-- opendfx_shell_i_RP_0_pp_pipeline_inst_0_partial.bit.bin | | | |-- opendfx_shell_i_RP_0_pp_pipeline_inst_0_partial.bit.bin_i.dtbo | | | `-- opendfx_shell_i_RP_0_pp_pipeline_inst_0_partial.bit.bin_i.dtsi | | `-- PP_PIPELINE_slot1 | | |-- accel.json | | |-- opendfx_shell_i_RP_1_pp_pipeline_inst_1_partial.bit.bin | | |-- opendfx_shell_i_RP_1_pp_pipeline_inst_1_partial.bit.bin_i.dtbo | | `-- opendfx_shell_i_RP_1_pp_pipeline_inst_1_partial.bit.bin_i.dtsi | |-- opendfx_shell_wrapper.bit.bin | |-- pl.dtbo | |-- pl.dtsi | `-- shell.json `-- kr260-tsn-rs485pmod |-- kr260-tsn-rs485pmod.bin |-- kr260-tsn-rs485pmod.dtbo `-- shell.json ```
and their dfx-mgrd representation: ``` $ sudo xmutil listapps Accelerator Accel_type Base Base_type #slots(PL+AIE) Active_slot k26-starter-kits XRT_FLAT k26-starter-kits XRT_FLAT (0+0) 0, kr260-tsn-rs485pmod XRT_FLAT kr260-tsn-rs485pmod XRT_FLAT (0+0) -1 FFT SIHA_PL_DFX k26_2rp_1409 PL_DFX (2+0) -1 PP_PIPELINE SIHA_PL_DFX k26_2rp_1409 PL_DFX (2+0) -1 FIR SIHA_PL_DFX k26_2rp_1409 PL_DFX (2+0) -1 DPU SIHA_PL_DFX k26_2rp_1409 PL_DFX (2+0) -1 AES128 SIHA_PL_DFX k26_2rp_1409 PL_DFX (2+0) -1 AES192 SIHA_PL_DFX k26_2rp_1409 PL_DFX (2+0) -1 ``` 2. Command to load one of the above listed accelerator. For dfx designs, base shell would be loaded first if not already loaded and then accelerator will be loaded to one of the free slots. If the shell is already loaded then only the accelerator will be loaded to one of free slots. If the device tree overlay (.dtbo) file contains **external-fpga-config** string the dfx-mgrd will use DFX_EXTERNAL_CONFIG_EN instead of the default DFX_NORMAL_EN flag when calling [libdfx](https://github.com/Xilinx/libdfx) fetch function. Equivalent xmutil command is `xmutil loadapp FFT`. ``` $ dfx-mgr-client -load FFT ``` 3. Command to remove accelerator from the slot. If there is not accel in the mentioned slot, this command will do nothing. Equivalent xmutil command is `xmutil unloadapp 1`. ``` $ dfx-mgr-client -remove 1 ``` ### Using library API Users can write application to interact with daemon. Refer to example source code in `repo/example/sys/linux/load_accel.c` for a simple example how to load an accelerator. ## Known limitations 1. DFX-MGR uses i-notify for firmware file updates and i-notify doesn't work with network filesystem. Hence it is recommended to NOT boot linux over NFS for correct functionality of DFX-MGR daemon. 2. DFX-MGR package names i.e. firmware folder names are limited to 64 character currently and absolute path lengths are limited to 512 char. Hence avoid creating long filenames. 3. I/O nodes don't support zero copy. dfx-mgr-xilinx_v2023.2/build.sh000077500000000000000000000004261446677152000164030ustar00rootroot00000000000000#!/bin/bash cmake ../ \ -DCMAKE_TOOLCHAIN_FILE=versal-linux \ -DCMAKE_INCLUDE_PATH="$(pwd)/../include" \ -DCMAKE_LIBRARY_PATH="$(pwd)/../opendfx-graph/drivers/XF2DFilter/src/lib/sw/aarch64-linux;" \ if [ $? -ne 0 ]; then exit 255 fi make VERBOSE=1 DESTDIR=$(pwd) install dfx-mgr-xilinx_v2023.2/cmake/000077500000000000000000000000001446677152000160235ustar00rootroot00000000000000dfx-mgr-xilinx_v2023.2/cmake/collect.cmake000066400000000000000000000026331446677152000204560ustar00rootroot00000000000000######################################################################### # Copyright (c) 2021, Xilinx Inc. and Contributors. All rights reserved. # SPDX-License-Identifier: MIT ######################################################################### function (collector_create name base) set_property (GLOBAL PROPERTY "COLLECT_${name}_LIST") set_property (GLOBAL PROPERTY "COLLECT_${name}_BASE" "${base}") endfunction (collector_create) function (collector_list var name) get_property (_list GLOBAL PROPERTY "COLLECT_${name}_LIST") set (${var} "${_list}" PARENT_SCOPE) endfunction (collector_list) function (collector_base var name) get_property (_base GLOBAL PROPERTY "COLLECT_${name}_BASE") set (${var} "${_base}" PARENT_SCOPE) endfunction (collector_base) function (collect name) collector_base (_base ${name}) string(COMPARE NOTEQUAL "${_base}" "" _is_rel) set (_list) foreach (s IN LISTS ARGN) if (_is_rel) get_filename_component (s "${s}" ABSOLUTE) file (RELATIVE_PATH s "${_base}" "${s}") endif (_is_rel) list (APPEND _list "${s}") endforeach () set_property (GLOBAL APPEND PROPERTY "COLLECT_${name}_LIST" "${_list}") endfunction (collect) # Create global collectors collector_create (PROJECT_INC_DIRS "") collector_create (PROJECT_LIB_DIRS "") collector_create (PROJECT_LIB_DEPS "") collector_create (PROJECT_HDR_TESTS "") # vim: expandtab:ts=2:sw=2:smartindent dfx-mgr-xilinx_v2023.2/cmake/options.cmake000066400000000000000000000033561446677152000205270ustar00rootroot00000000000000######################################################################### # Copyright (c) 2021, Xilinx Inc. and Contributors. All rights reserved. # SPDX-License-Identifier: MIT ######################################################################### #PROJECT_VERSION should match with yocto recipe version for SOVERSION set (PROJECT_VERSION_MAJOR 1) set (PROJECT_VERSION_MINOR 0) set (PROJECT_VERSION ${PROJECT_VERSION_MAJOR}.${PROJECT_VERSION_MINOR}) message (STATUS "dfx-mgr version: ${PROJECT_VERSION} (${CMAKE_SOURCE_DIR})") if (NOT CMAKE_BUILD_TYPE) set (CMAKE_BUILD_TYPE Debug) endif (NOT CMAKE_BUILD_TYPE) message ("-- Build type: ${CMAKE_BUILD_TYPE}") if (NOT CMAKE_INSTALL_LIBDIR) set (CMAKE_INSTALL_LIBDIR "lib") endif (NOT CMAKE_INSTALL_LIBDIR) if (NOT CMAKE_INSTALL_BINDIR) set (CMAKE_INSTALL_BINDIR "bin") endif (NOT CMAKE_INSTALL_BINDIR) set (_host "${CMAKE_HOST_SYSTEM_NAME}/${CMAKE_HOST_SYSTEM_PROCESSOR}") message ("-- Host: ${_host}") set (_target "${CMAKE_SYSTEM_NAME}/${CMAKE_SYSTEM_PROCESSOR}") message ("-- Target: ${_target}") if (NOT DEFINED MACHINE) set (MACHINE "Generic") endif (NOT DEFINED MACHINE) message ("-- Machine: ${MACHINE}") # handle if '-' in machine name string (REPLACE "-" "_" MACHINE ${MACHINE}) if (NOT DEFINED PROJECT_SYSTEM) string (TOLOWER ${CMAKE_SYSTEM_NAME} PROJECT_SYSTEM) string (TOUPPER ${CMAKE_SYSTEM_NAME} PROJECT_SYSTEM_UPPER) endif (NOT DEFINED PROJECT_SYSTEM) option (WITH_STATIC_LIB "Build with a static library" ON) if ("${PROJECT_SYSTEM}" STREQUAL "linux") option (WITH_SHARED_LIB "Build with a shared library" ON) endif ("${PROJECT_SYSTEM}" STREQUAL "linux") set_property (GLOBAL PROPERTY "PROJECT_EC_FLAGS" -Wall -Werror -Wextra) # vim: expandtab:ts=2:sw=2:smartindent dfx-mgr-xilinx_v2023.2/cmake/platforms/000077500000000000000000000000001446677152000200325ustar00rootroot00000000000000dfx-mgr-xilinx_v2023.2/cmake/platforms/cross-generic-gcc.cmake000066400000000000000000000012431446677152000243310ustar00rootroot00000000000000######################################################################### # Copyright (c) 2021, Xilinx Inc. and Contributors. All rights reserved. # SPDX-License-Identifier: MIT ######################################################################### set (CMAKE_SYSTEM_NAME "Generic" CACHE STRING "") set (CMAKE_FIND_ROOT_PATH_MODE_PROGRAM NEVER CACHE STRING "") set (CMAKE_FIND_ROOT_PATH_MODE_LIBRARY NEVER CACHE STRING "") set (CMAKE_FIND_ROOT_PATH_MODE_INCLUDE NEVER CACHE STRING "") include (CMakeForceCompiler) CMAKE_FORCE_C_COMPILER ("${CROSS_PREFIX}gcc" GNU) CMAKE_FORCE_CXX_COMPILER ("${CROSS_PREFIX}g++" GNU) # vim: expandtab:ts=2:sw=2:smartindent dfx-mgr-xilinx_v2023.2/cmake/platforms/cross-linux-gcc.cmake000066400000000000000000000012311446677152000240510ustar00rootroot00000000000000######################################################################### # Copyright (c) 2021, Xilinx Inc. and Contributors. All rights reserved. # SPDX-License-Identifier: MIT ######################################################################### set (CMAKE_SYSTEM_NAME "Linux" CACHE STRING "") set (CMAKE_C_COMPILER "${CROSS_PREFIX}gcc" CACHE STRING "") set (CMAKE_CXX_COMPILER "${CROSS_PREFIX}g++" CACHE STRING "") set (CMAKE_FIND_ROOT_PATH_MODE_PROGRAM NEVER CACHE STRING "") set (CMAKE_FIND_ROOT_PATH_MODE_LIBRARY NEVER CACHE STRING "") set (CMAKE_FIND_ROOT_PATH_MODE_INCLUDE NEVER CACHE STRING "") # vim: expandtab:ts=2:sw=2:smartindent dfx-mgr-xilinx_v2023.2/cmake/platforms/versal-a72-generic.cmake000066400000000000000000000010461446677152000243320ustar00rootroot00000000000000######################################################################### # Copyright (c) 2021, Xilinx Inc. and Contributors. All rights reserved. # SPDX-License-Identifier: MIT ######################################################################### set (CMAKE_SYSTEM_PROCESSOR "aarch64" CACHE STRING "") set (CROSS_PREFIX "aarch64-none-elf-" CACHE STRING "") set (CMAKE_C_FLAGS "-mcpu=cortex-a72 -DDEBUG -Wall -Wextra -Werror -Os" CACHE STRING "") include (cross-generic-gcc) # vim: expandtab:ts=2:sw=2:smartindent dfx-mgr-xilinx_v2023.2/cmake/platforms/versal-linux.cmake000066400000000000000000000010051446677152000234610ustar00rootroot00000000000000######################################################################### # Copyright (c) 2021, Xilinx Inc. and Contributors. All rights reserved. # SPDX-License-Identifier: MIT ######################################################################### set (CMAKE_SYSTEM_PROCESSOR "aarch64" CACHE STRING "") set (CROSS_PREFIX "aarch64-linux-gnu-" CACHE STRING "") set (CMAKE_C_FLAGS " -Wall -Wextra -Werror -Os" CACHE STRING "") include (cross-linux-gcc) # vim: expandtab:ts=2:sw=2:smartindent dfx-mgr-xilinx_v2023.2/example/000077500000000000000000000000001446677152000163765ustar00rootroot00000000000000dfx-mgr-xilinx_v2023.2/example/CMakeLists.txt000066400000000000000000000005351446677152000211410ustar00rootroot00000000000000######################################################################### # Copyright (c) 2021, Xilinx Inc. and Contributors. All rights reserved. # SPDX-License-Identifier: MIT ######################################################################### collect(PROJECT_LIB_DEPS acapd) add_subdirectory (sys) # vim: expandtab:ts=2:sw=2:smartindent dfx-mgr-xilinx_v2023.2/example/sys/000077500000000000000000000000001446677152000172145ustar00rootroot00000000000000dfx-mgr-xilinx_v2023.2/example/sys/CMakeLists.txt000066400000000000000000000002361446677152000217550ustar00rootroot00000000000000 if (EXISTS ${CMAKE_CURRENT_SOURCE_DIR}/${PROJECT_SYSTEM}) add_subdirectory(${PROJECT_SYSTEM}) endif (EXISTS ${CMAKE_CURRENT_SOURCE_DIR}/${PROJECT_SYSTEM}) dfx-mgr-xilinx_v2023.2/example/sys/generic/000077500000000000000000000000001446677152000206305ustar00rootroot00000000000000dfx-mgr-xilinx_v2023.2/example/sys/generic/CMakeLists.txt000066400000000000000000000036021446677152000233710ustar00rootroot00000000000000######################################################################### # Copyright (c) 2021, Xilinx Inc. and Contributors. All rights reserved. # SPDX-License-Identifier: MIT ######################################################################### find_path (_include_dir xparameters.h) if (NOT _include_dir) message (FATAL_ERROR "xparameter.h not find") endif (NOT _include_dir) collect (PROJECT_INC_DIRS ${_include_dir}) collector_list (_list PROJECT_INC_DIRS) include_directories (${_list} ${CMAKE_CURRENT_SOURCE_DIR}) set (_lib "xilfpga") find_library (_lib_path ${_lib}) if (NOT _lib_path) message ( "external library ${_lib_path} not found" ) message ( "hint: you may need to pass -DCMAKE_LIBRARY_PATH=" ) message ( FATAL_ERROR "library ${_lib} is required to build the examples" ) endif (NOT _lib_path) list (APPEND _lib "xilmailbox") list (APPEND _lib "xil") list (APPEND _lib "c") list (APPEND _lib "m") get_filename_component (_lib_path ${_lib_path} DIRECTORY) collect (PROJECT_LIB_DIRS ${_lib_path}) collector_list (_list PROJECT_LIB_DIRS) link_directories (${_list}) set (_linker_script ${CMAKE_CURRENT_SOURCE_DIR}/lscript.ld) include_directories(${CMAKE_CURRENT_BINARY_DIR}) configure_file(accel-config.h.in accel-config.h @ONLY) foreach (_app accel-pr) set (_src ${CMAKE_CURRENT_SOURCE_DIR}/${_app}.c accel-config.s) list (APPEND _src accel-config.s) set_source_files_properties(accel-config.s PROPERTIES COMPILE_FLAGS "-x assembler-with-cpp") add_executable (${_app}.elf ${_src}) if (PROJECT_EC_FLAGS) string(REPLACE " " ";" _ec_flgs ${PROJECT_EC_FLAGS}) target_compile_options (${_app}-static PUBLIC ${_ec_flgs}) endif (PROJECT_EC_FLAGS) target_link_libraries(${_app}.elf -Wl,-Map=${_app0}.map -Wl,--gc-sections -T\"${_linker_script}\" -Wl,--start-group acapd ${_lib} -Wl,--end-group) install (TARGETS ${_app}.elf RUNTIME DESTINATION bin) endforeach (_app) dfx-mgr-xilinx_v2023.2/example/sys/generic/accel-config.h.in000066400000000000000000000005111446677152000237150ustar00rootroot00000000000000/* * Copyright (c) 2021, Xilinx Inc. and Contributors. All rights reserved. * * SPDX-License-Identifier: MIT */ #ifndef __ACAPD_ACCEL_CONFIG_H #define __ACAPD_ACCEL_CONFIG_H #define ACAPD_SHELL_JSON "@ACAPD_SHELL_JSON@" #define ACAPD_ACCEL0_JSON "@ACAPD_ACCEL0_JSON@" #define ACAPD_ACCEL0_PDI "@ACAPD_ACCEL0_PDI@" #endif dfx-mgr-xilinx_v2023.2/example/sys/generic/accel-config.s000066400000000000000000000013671446677152000233350ustar00rootroot00000000000000/* * Copyright (c) 2021, Xilinx Inc. and Contributors. All rights reserved. * * SPDX-License-Identifier: MIT */ #include "accel-config.h" .section .rodata .global __START_SHELL_JSON .global __END_SHELL_JSON .global __START_ACCEL0_JSON .global __END_ACCEL0_JSON .global __START_ACCEL0_PDI .global __END_ACCEL0_PDI .global __START_ACCEL0 .global __END_ACCEL0 .align 16 __START_SHELL_JSON: .incbin ACAPD_SHELL_JSON __END_SHELL_JSON: .align 16 __START_ACCEL0_JSON: .incbin ACAPD_ACCEL0_JSON __END_ACCEL0_JSON: .align 16 __START_ACCEL0_PDI: .incbin ACAPD_ACCEL0_PDI __END_ACCEL0_PDI: .align 16 __START_ACCEL0: .8byte __START_ACCEL0_JSON,__END_ACCEL0_JSON-__START_ACCEL0_JSON .8byte __START_ACCEL0_PDI,__END_ACCEL0_PDI-__START_ACCEL0_PDI __END_ACCEL0: dfx-mgr-xilinx_v2023.2/example/sys/generic/accel-pr.c000066400000000000000000000052441446677152000224670ustar00rootroot00000000000000/* * Copyright (c) 2021, Xilinx Inc. and Contributors. All rights reserved. * * SPDX-License-Identifier: MIT */ #include #include #include #include #include #include #define DATA_SIZE_BYTES (4*1024) extern unsigned char __START_ACCEL0[]; static acapd_shm_t tx_shm, rx_shm; int main(void) { void *tx_va, *rx_va; uint32_t *dptr; int ret; acapd_accel_pkg_hd_t *pkg1; //acapd_accel_pkg_hd_t *pkg2; acapd_accel_t accel; //int ret; /* Configure packages */ /* TODO: This step should be replaced by host tool. */ xil_printf("allocate memory for package\r\n"); pkg1 = (acapd_accel_pkg_hd_t *)__START_ACCEL0; /* Initialize accelerator with package */ xil_printf("Initialize accelerator with packge.\r\n"); init_accel(&accel, pkg1); /* Load accelerator */ xil_printf("Load accelerator with packge.\r\n"); ret = load_accel(&accel, 0); if (ret != 0) { xil_printf("ERROR: failed to load accel.\n"); return -1; } memset(&tx_shm, 0, sizeof(tx_shm)); memset(&rx_shm, 0, sizeof(rx_shm)); tx_va = acapd_accel_alloc_shm(&accel, DATA_SIZE_BYTES, &tx_shm); if (tx_va == NULL) { xil_printf("ERROR: Failed to allocate tx memory.\n"); ret = -EINVAL; goto error; } dptr = (uint32_t *)tx_va; for (uint32_t i = 0; i < DATA_SIZE_BYTES/4; i++) { *((uint32_t *)dptr) = i + 1; dptr++; } rx_va = acapd_accel_alloc_shm(&accel, DATA_SIZE_BYTES, &rx_shm); if (rx_va == NULL) { xil_printf("ERROR: allocate rx memory.\n"); ret = -EINVAL; goto error; } /* user can use acapd_accel_get_reg_va() to get accelerator address */ /* Transfer data */ ret = acapd_accel_write_data(&accel, &tx_shm, tx_va, DATA_SIZE_BYTES, 0); if (ret < 0) { xil_printf("ERROR: Failed to write to accelerator.\n"); ret = -EINVAL; goto error; } /* TODO: Execute acceleration (optional as load_accel can also start * it from CDO */ /* Wait for output data ready */ /* For now, this function force to return 1 as no ready pin can poke */ ret = acapd_accel_wait_for_data_ready(&accel); if (ret < 0) { xil_printf("Failed to check if accelerator is ready.\n"); ret = -EINVAL; goto error; } /* Read data */ ret = acapd_accel_read_data(&accel, &rx_shm, rx_va, DATA_SIZE_BYTES, 1); if (ret < 0) { xil_printf("Failed to read from accelerator.\n"); return -EINVAL; } dptr = (uint32_t *)rx_va; for (uint32_t i = 0; i < DATA_SIZE_BYTES/4; i++) { if (*((uint32_t *)dptr) != (i + 1)) { xil_printf("ERROR: wrong data: [%d]: 0x%x.\n", i, *((volatile uint32_t *)dptr)); ret = -EINVAL; goto error; } dptr++; } ret = 0; printf("Test Done.\n"); sleep(2); error: remove_accel(&accel, 0); return ret; } dfx-mgr-xilinx_v2023.2/example/sys/generic/lscript.ld000066400000000000000000000166421446677152000226420ustar00rootroot00000000000000/*******************************************************************/ /* */ /* This file is automatically generated by linker script generator.*/ /* */ /* Version: 2019.2 */ /* Description : ARM v8 Linker Script */ /* Copyright (c) 2021, Xilinx Inc. and Contributors. All rights reserved. /* /* SPDX-License-Identifier: MIT /*******************************************************************/ _STACK_SIZE = DEFINED(_STACK_SIZE) ? _STACK_SIZE : 0x100000; _HEAP_SIZE = DEFINED(_HEAP_SIZE) ? _HEAP_SIZE : 0x800000; _EL0_STACK_SIZE = DEFINED(_EL0_STACK_SIZE) ? _EL0_STACK_SIZE : 1024; _EL1_STACK_SIZE = DEFINED(_EL1_STACK_SIZE) ? _EL1_STACK_SIZE : 2048; _EL2_STACK_SIZE = DEFINED(_EL2_STACK_SIZE) ? _EL2_STACK_SIZE : 1024; /* Define Memories in the system */ MEMORY { ddr_mem_NOC_0_C0_DDR_LOW0 : ORIGIN = 0x0, LENGTH = 0x80000000 ddr_mem_NOC_0_C0_DDR_LOW0 : ORIGIN = 0x0, LENGTH = 0x80000000 ddr_mem_NOC_0_C0_DDR_LOW0 : ORIGIN = 0x0, LENGTH = 0x80000000 ddr_mem_NOC_0_C0_DDR_LOW0 : ORIGIN = 0x0, LENGTH = 0x80000000 ddr_mem_NOC_0_C0_DDR_LOW0 : ORIGIN = 0x0, LENGTH = 0x80000000 ddr_mem_NOC_0_C0_DDR_LOW0 : ORIGIN = 0x0, LENGTH = 0x80000000 ddr_mem_NOC_0_C0_DDR_LOW0 : ORIGIN = 0x0, LENGTH = 0x80000000 psv_ocm_ram_0_MEM_0 : ORIGIN = 0xFFFC0000, LENGTH = 0x40000 psv_pmc_qspi_ospi_flash_0_MEM_0 : ORIGIN = 0xC0000000, LENGTH = 0x20000000 psv_r5_0_atcm_global_MEM_0 : ORIGIN = 0xFFE00000, LENGTH = 0x10000 psv_r5_0_atcm_lockstep_MEM_0 : ORIGIN = 0xFFE10000, LENGTH = 0x10000 psv_r5_0_btcm_global_MEM_0 : ORIGIN = 0xFFE20000, LENGTH = 0x10000 psv_r5_0_btcm_lockstep_MEM_0 : ORIGIN = 0xFFE30000, LENGTH = 0x10000 psv_r5_1_atcm_global_MEM_0 : ORIGIN = 0xFFE90000, LENGTH = 0x10000 psv_r5_1_btcm_global_MEM_0 : ORIGIN = 0xFFEB0000, LENGTH = 0x10000 psv_r5_tcm_ram_global_MEM_0 : ORIGIN = 0xFFE00000, LENGTH = 0x40000 apu_peri_axi_bram_ctrl_0_Mem0 : ORIGIN = 0xA4000000, LENGTH = 0x4000 } /* Specify the default entry point to the program */ ENTRY(_vector_table) /* Define the sections, and where they are mapped in memory */ SECTIONS { .text : { KEEP (*(.vectors)) *(.boot) *(.text) *(.text.*) *(.gnu.linkonce.t.*) *(.plt) *(.gnu_warning) *(.gcc_execpt_table) *(.glue_7) *(.glue_7t) *(.ARM.extab) *(.gnu.linkonce.armextab.*) } > ddr_mem_NOC_0_C0_DDR_LOW0 .init (ALIGN(64)) : { KEEP (*(.init)) } > ddr_mem_NOC_0_C0_DDR_LOW0 .fini (ALIGN(64)) : { KEEP (*(.fini)) } > ddr_mem_NOC_0_C0_DDR_LOW0 .interp : { KEEP (*(.interp)) } > ddr_mem_NOC_0_C0_DDR_LOW0 .note-ABI-tag : { KEEP (*(.note-ABI-tag)) } > ddr_mem_NOC_0_C0_DDR_LOW0 .rodata : { . = ALIGN(64); __rodata_start = .; *(.rodata) *(.rodata.*) *(.gnu.linkonce.r.*) __rodata_end = .; } > ddr_mem_NOC_0_C0_DDR_LOW0 .rodata1 : { . = ALIGN(64); __rodata1_start = .; *(.rodata1) *(.rodata1.*) __rodata1_end = .; } > ddr_mem_NOC_0_C0_DDR_LOW0 .sdata2 : { . = ALIGN(64); __sdata2_start = .; *(.sdata2) *(.sdata2.*) *(.gnu.linkonce.s2.*) __sdata2_end = .; } > ddr_mem_NOC_0_C0_DDR_LOW0 .sbss2 : { . = ALIGN(64); __sbss2_start = .; *(.sbss2) *(.sbss2.*) *(.gnu.linkonce.sb2.*) __sbss2_end = .; } > ddr_mem_NOC_0_C0_DDR_LOW0 .data : { . = ALIGN(64); __data_start = .; *(.data) *(.data.*) *(.gnu.linkonce.d.*) *(.jcr) *(.got) *(.got.plt) __data_end = .; } > ddr_mem_NOC_0_C0_DDR_LOW0 .data1 : { . = ALIGN(64); __data1_start = .; *(.data1) *(.data1.*) __data1_end = .; } > ddr_mem_NOC_0_C0_DDR_LOW0 .got : { *(.got) } > ddr_mem_NOC_0_C0_DDR_LOW0 .got1 : { *(.got1) } > ddr_mem_NOC_0_C0_DDR_LOW0 .got2 : { *(.got2) } > ddr_mem_NOC_0_C0_DDR_LOW0 .ctors : { . = ALIGN(64); __CTOR_LIST__ = .; ___CTORS_LIST___ = .; KEEP (*crtbegin.o(.ctors)) KEEP (*(EXCLUDE_FILE(*crtend.o) .ctors)) KEEP (*(SORT(.ctors.*))) KEEP (*(.ctors)) __CTOR_END__ = .; ___CTORS_END___ = .; } > ddr_mem_NOC_0_C0_DDR_LOW0 .dtors : { . = ALIGN(64); __DTOR_LIST__ = .; ___DTORS_LIST___ = .; KEEP (*crtbegin.o(.dtors)) KEEP (*(EXCLUDE_FILE(*crtend.o) .dtors)) KEEP (*(SORT(.dtors.*))) KEEP (*(.dtors)) __DTOR_END__ = .; ___DTORS_END___ = .; } > ddr_mem_NOC_0_C0_DDR_LOW0 .fixup : { __fixup_start = .; *(.fixup) __fixup_end = .; } > ddr_mem_NOC_0_C0_DDR_LOW0 .eh_frame : { *(.eh_frame) } > ddr_mem_NOC_0_C0_DDR_LOW0 .eh_framehdr : { __eh_framehdr_start = .; *(.eh_framehdr) __eh_framehdr_end = .; } > ddr_mem_NOC_0_C0_DDR_LOW0 .gcc_except_table : { *(.gcc_except_table) } > ddr_mem_NOC_0_C0_DDR_LOW0 .mmu_tbl0 (ALIGN(4096)) : { __mmu_tbl0_start = .; *(.mmu_tbl0) __mmu_tbl0_end = .; } > ddr_mem_NOC_0_C0_DDR_LOW0 .mmu_tbl1 (ALIGN(4096)) : { __mmu_tbl1_start = .; *(.mmu_tbl1) __mmu_tbl1_end = .; } > ddr_mem_NOC_0_C0_DDR_LOW0 .mmu_tbl2 (ALIGN(4096)) : { __mmu_tbl2_start = .; *(.mmu_tbl2) __mmu_tbl2_end = .; } > ddr_mem_NOC_0_C0_DDR_LOW0 .ARM.exidx : { __exidx_start = .; *(.ARM.exidx*) *(.gnu.linkonce.armexidix.*.*) __exidx_end = .; } > ddr_mem_NOC_0_C0_DDR_LOW0 .preinit_array : { . = ALIGN(64); __preinit_array_start = .; KEEP (*(SORT(.preinit_array.*))) KEEP (*(.preinit_array)) __preinit_array_end = .; } > ddr_mem_NOC_0_C0_DDR_LOW0 .init_array : { . = ALIGN(64); __init_array_start = .; KEEP (*(SORT(.init_array.*))) KEEP (*(.init_array)) __init_array_end = .; } > ddr_mem_NOC_0_C0_DDR_LOW0 .fini_array : { . = ALIGN(64); __fini_array_start = .; KEEP (*(SORT(.fini_array.*))) KEEP (*(.fini_array)) __fini_array_end = .; } > ddr_mem_NOC_0_C0_DDR_LOW0 .ARM.attributes : { __ARM.attributes_start = .; *(.ARM.attributes) __ARM.attributes_end = .; } > ddr_mem_NOC_0_C0_DDR_LOW0 .sdata : { . = ALIGN(64); __sdata_start = .; *(.sdata) *(.sdata.*) *(.gnu.linkonce.s.*) __sdata_end = .; } > ddr_mem_NOC_0_C0_DDR_LOW0 .sbss (NOLOAD) : { . = ALIGN(64); __sbss_start = .; *(.sbss) *(.sbss.*) *(.gnu.linkonce.sb.*) . = ALIGN(64); __sbss_end = .; } > ddr_mem_NOC_0_C0_DDR_LOW0 .tdata : { . = ALIGN(64); __tdata_start = .; *(.tdata) *(.tdata.*) *(.gnu.linkonce.td.*) __tdata_end = .; } > ddr_mem_NOC_0_C0_DDR_LOW0 .tbss : { . = ALIGN(64); __tbss_start = .; *(.tbss) *(.tbss.*) *(.gnu.linkonce.tb.*) __tbss_end = .; } > ddr_mem_NOC_0_C0_DDR_LOW0 .bss (NOLOAD) : { . = ALIGN(64); __bss_start__ = .; *(.bss) *(.bss.*) *(.gnu.linkonce.b.*) *(COMMON) . = ALIGN(64); __bss_end__ = .; } > ddr_mem_NOC_0_C0_DDR_LOW0 _SDA_BASE_ = __sdata_start + ((__sbss_end - __sdata_start) / 2 ); _SDA2_BASE_ = __sdata2_start + ((__sbss2_end - __sdata2_start) / 2 ); /* Generate Stack and Heap definitions */ .heap (NOLOAD) : { . = ALIGN(64); _heap = .; HeapBase = .; _heap_start = .; . += _HEAP_SIZE; _heap_end = .; HeapLimit = .; } > ddr_mem_NOC_0_C0_DDR_LOW0 .stack (NOLOAD) : { . = ALIGN(64); _el3_stack_end = .; . += _STACK_SIZE; __el3_stack = .; _el2_stack_end = .; . += _EL2_STACK_SIZE; . = ALIGN(64); __el2_stack = .; _el1_stack_end = .; . += _EL1_STACK_SIZE; . = ALIGN(64); __el1_stack = .; _el0_stack_end = .; . += _EL0_STACK_SIZE; . = ALIGN(64); __el0_stack = .; } > ddr_mem_NOC_0_C0_DDR_LOW0 _end = .; } dfx-mgr-xilinx_v2023.2/example/sys/linux/000077500000000000000000000000001446677152000203535ustar00rootroot00000000000000dfx-mgr-xilinx_v2023.2/example/sys/linux/CMakeLists.txt000066400000000000000000000033451446677152000231200ustar00rootroot00000000000000######################################################################### # Copyright (c) 2021, Xilinx Inc. and Contributors. All rights reserved. # SPDX-License-Identifier: MIT ######################################################################### # add_subdirectory (graph) collector_list (_list PROJECT_INC_DIRS) include_directories (${_list} ${CMAKE_CURRENT_SOURCE_DIR}) collector_list (_list PROJECT_LIB_DIRS) link_directories (${_list}) SET(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -pthread") set (_deps "dfx" "dl" "pthread") foreach (_app load_accel accel-bzip2 accel-shm accel-aes accel-container dfx-mgr-client dfx-mgrd ) #foreach (_app load_accel dfx-mgr-client dfx-mgrd dfx-mgrd2 graphTest6) set (_src ${CMAKE_CURRENT_SOURCE_DIR}/${_app}.c) if (WITH_SHARED_LIB) add_executable (${_app}-share ${_src}) if (PROJECT_EC_FLAGS) string(REPLACE " " ";" _ec_flgs ${PROJECT_EC_FLAGS}) target_compile_options (${_app}-share PUBLIC ${_ec_flgs}) endif (PROJECT_EC_FLAGS) target_link_libraries (${_app}-share ${PROJECT_NAME}-shared ${_deps}) install (TARGETS ${_app}-share RUNTIME DESTINATION bin) add_dependencies (${_app}-share ${PROJECT_NAME}-shared) endif (WITH_SHARED_LIB) if (WITH_STATIC_LIB) if (${PROJECT_SYSTEM} STREQUAL "linux") add_executable (${_app}-static ${_src}) if (PROJECT_EC_FLAGS) string(REPLACE " " ";" _ec_flgs ${PROJECT_EC_FLAGS}) target_compile_options (${_app}-static PUBLIC ${_ec_flgs}) endif (PROJECT_EC_FLAGS) target_link_libraries (${_app}-static ${PROJECT_NAME}-static ${_deps}) install (TARGETS ${_app}-static RUNTIME DESTINATION bin) endif (${PROJECT_SYSTEM} STREQUAL "linux") endif (WITH_STATIC_LIB) endforeach (_app) dfx-mgr-xilinx_v2023.2/example/sys/linux/accel-aes.c000066400000000000000000000051151446677152000223360ustar00rootroot00000000000000/* * Copyright (c) 2021, Xilinx Inc. and Contributors. All rights reserved. * * SPDX-License-Identifier: MIT */ #include #include #include #include #include #include #include #include #include #include #define DATA_SIZE_BYTES (4*1024) static acapd_accel_t bzip2_accel; static acapd_device_t shell_dev; static acapd_device_t rm_dev; static acapd_device_t ip_dev[2]; static acapd_device_t dma_dev; static acapd_chnl_t chnls[2]; void usage (const char *cmd) { fprintf(stdout, "Usage %s -p \n", cmd); } void sig_handler(int signo) { (void)signo; remove_accel(&bzip2_accel, 0); } int main(int argc, char *argv[]) { int opt; char *pkg_path = NULL; int ret; void *va; uint32_t v; while ((opt = getopt(argc, argv, "p:")) != -1) { switch (opt) { case 'p': pkg_path = optarg; break; default: usage(argv[0]); return -EINVAL; } } if (pkg_path == NULL) { usage(argv[0]); return -EINVAL; } printf("Setting accel devices.\n"); memset(&shell_dev, 0, sizeof(shell_dev)); memset(&rm_dev, 0, sizeof(rm_dev)); memset(&ip_dev, 0, sizeof(ip_dev)); memset(&dma_dev, 0, sizeof(dma_dev)); shell_dev.dev_name = "90000000.gpio"; ip_dev[0].dev_name = "20100000000.ap_start"; ip_dev[1].dev_name = "20100001000.key"; dma_dev.dev_name = "a4000000.dma"; dma_dev.driver = "vfio-platform"; dma_dev.iommu_group = 0; /* TODO adding channels to acceleration */ memset(chnls, 0, sizeof(chnls)); chnls[0].dev = &dma_dev; chnls[0].ops = &axidma_vfio_dma_ops; chnls[0].dir = ACAPD_DMA_DEV_W; chnls[1].dev = &dma_dev; chnls[1].ops = &axidma_vfio_dma_ops; chnls[1].dir = ACAPD_DMA_DEV_R; /* allocate memory */ printf("Initializing accel with %s.\n", pkg_path); init_accel(&bzip2_accel, (acapd_accel_pkg_hd_t *)pkg_path); bzip2_accel.num_ip_devs = 2; bzip2_accel.ip_dev = ip_dev; bzip2_accel.shell_dev = &shell_dev; bzip2_accel.chnls = chnls; bzip2_accel.num_chnls = 2; signal(SIGINT, sig_handler); printf("Loading accel %s.\n", pkg_path); ret = load_accel(&bzip2_accel,NULL, 0); if (ret != 0) { fprintf(stderr, "ERROR: failed to load accel.\n"); goto error; } va = acapd_accel_get_reg_va(&bzip2_accel, ip_dev[1].dev_name); *((volatile uint32_t *)va) = 0xdeadbeef; v = *((volatile uint32_t *)va); if (v != 0xdeadbeef) { fprintf(stderr, "ERROR: failed to read from accel: 0x%x.\n", v); ret = -1; goto error; } ret = 0; printf("Test Done.\n"); error: printf("Removing accel %s.\n", pkg_path); remove_accel(&bzip2_accel, 0); return ret; } dfx-mgr-xilinx_v2023.2/example/sys/linux/accel-bzip2.c000066400000000000000000000016701446677152000226160ustar00rootroot00000000000000/* * Copyright (c) 2021, Xilinx Inc. and Contributors. All rights reserved. * * SPDX-License-Identifier: MIT */ #include #include #include #include #include #include void usage (const char *cmd) { fprintf(stdout, "Usage %s -p \n", cmd); } int main(int argc, char *argv[]) { int opt; char *pkg_path = NULL; acapd_accel_t bzip2_accel; while ((opt = getopt(argc, argv, "p:")) != -1) { switch (opt) { case 'p': pkg_path = optarg; break; default: usage(argv[0]); return -EINVAL; } } if (pkg_path == NULL) { usage(argv[0]); return -EINVAL; } printf("Initializing accel with %s.\n", pkg_path); init_accel(&bzip2_accel, (acapd_accel_pkg_hd_t *)pkg_path); printf("Loading accel %s.\n", pkg_path); load_accel(&bzip2_accel, NULL, 0); sleep(2); printf("Removing accel %s.\n", pkg_path); remove_accel(&bzip2_accel, 0); return 0; } dfx-mgr-xilinx_v2023.2/example/sys/linux/accel-container.c000066400000000000000000000030101446677152000235400ustar00rootroot00000000000000/* * Copyright (c) 2021, Xilinx Inc. and Contributors. All rights reserved. * * SPDX-License-Identifier: MIT */ #include #include #include #include #include #include #include #include #include #include static acapd_accel_t bzip2_accel; void usage (const char *cmd) { fprintf(stdout, "Usage %s -p -a \n", cmd); } void sig_handler(int signo) { (void)signo; printf("Removing accel.\n"); remove_accel(&bzip2_accel, 0); } int main(int argc, char *argv[]) { int opt; char *pkg_path = NULL; char *app_path = NULL; int ret; while ((opt = getopt(argc, argv, "p:a:")) != -1) { switch (opt) { case 'p': pkg_path = optarg; break; case 'a': app_path = optarg; break; default: usage(argv[0]); return -EINVAL; } } if (pkg_path == NULL || app_path == NULL) { usage(argv[0]); return -EINVAL; } printf("Setting accel devices.\n"); /* The Json Parsor is supposed to fill in this information */ /* allocate memory */ printf("Initializing accel with %s.\n", pkg_path); init_accel(&bzip2_accel, (acapd_accel_pkg_hd_t *)pkg_path); signal(SIGINT, sig_handler); printf("Loading accel %s.\n", pkg_path); ret = load_accel(&bzip2_accel, NULL, 0); if (ret != 0) { fprintf(stderr, "ERROR: failed to load accel.\n"); goto error; } /* run user application */ error: printf("Removing accel %s.\n", pkg_path); remove_accel(&bzip2_accel, 0); return ret; } dfx-mgr-xilinx_v2023.2/example/sys/linux/accel-shm.c000066400000000000000000000061031446677152000223530ustar00rootroot00000000000000/* * Copyright (c) 2021, Xilinx Inc. and Contributors. All rights reserved. * * SPDX-License-Identifier: MIT */ #include #include #include #include #include #include #include #include #include #include #define DATA_SIZE_BYTES (4*1024) static acapd_accel_t bzip2_accel; static acapd_shm_t tx_shm, rx_shm; void usage (const char *cmd) { fprintf(stdout, "Usage %s -p \n", cmd); } void sig_handler(int signo) { (void)signo; remove_accel(&bzip2_accel, 0); } int main(int argc, char *argv[]) { int opt; char *pkg_path = NULL; int ret; void *tx_va, *rx_va; uint32_t *dptr; while ((opt = getopt(argc, argv, "p:")) != -1) { switch (opt) { case 'p': pkg_path = optarg; break; default: usage(argv[0]); return -EINVAL; } } if (pkg_path == NULL) { usage(argv[0]); return -EINVAL; } printf("Setting accel devices.\n"); /* allocate memory */ printf("Initializing accel with %s.\n", pkg_path); init_accel(&bzip2_accel, (acapd_accel_pkg_hd_t *)pkg_path); signal(SIGINT, sig_handler); printf("Loading accel %s.\n", pkg_path); ret = load_accel(&bzip2_accel, NULL, 0); if (ret != 0) { fprintf(stderr, "ERROR: failed to load accel.\n"); goto error; } memset(&tx_shm, 0, sizeof(tx_shm)); memset(&rx_shm, 0, sizeof(rx_shm)); tx_va = acapd_accel_alloc_shm(&bzip2_accel, DATA_SIZE_BYTES, &tx_shm); if (tx_va == NULL) { fprintf(stderr, "ERROR: Failed to allocate tx memory.\n"); ret = -EINVAL; goto error; } dptr = (uint32_t *)tx_va; for (uint32_t i = 0; i < DATA_SIZE_BYTES/4; i++) { *((uint32_t *)dptr) = i + 1; dptr++; } rx_va = acapd_accel_alloc_shm(&bzip2_accel, DATA_SIZE_BYTES, &rx_shm); if (rx_va == NULL) { fprintf(stderr, "ERROR: allocate rx memory.\n"); ret = -EINVAL; goto error; } /* user can use acapd_accel_get_reg_va() to get accelerator address */ /* Transfer data */ ret = acapd_accel_write_data(&bzip2_accel, &tx_shm, tx_va, DATA_SIZE_BYTES, 0, 0); if (ret < 0) { fprintf(stderr, "ERROR: Failed to write to accelerator.\n"); ret = -EINVAL; goto error; } /* TODO: Execute acceleration (optional as load_accel can also start * it from CDO */ /* Wait for output data ready */ /* For now, this function force to return 1 as no ready pin can poke */ ret = acapd_accel_wait_for_data_ready(&bzip2_accel); if (ret < 0) { fprintf(stderr, "Failed to check if accelerator is ready.\n"); ret = -EINVAL; goto error; } /* Read data */ ret = acapd_accel_read_data(&bzip2_accel, &rx_shm, rx_va, DATA_SIZE_BYTES, 1); if (ret < 0) { fprintf(stderr, "Failed to read from accelerator.\n"); return -EINVAL; } dptr = (uint32_t *)rx_va; for (uint32_t i = 0; i < DATA_SIZE_BYTES/4; i++) { if (*((uint32_t *)dptr) != (i + 1)) { fprintf(stderr, "ERROR: wrong data: [%d]: 0x%x.\n", i, *((volatile uint32_t *)dptr)); ret = -EINVAL; goto error; } dptr++; } ret = 0; printf("Test Done.\n"); error: printf("Removing accel %s.\n", pkg_path); remove_accel(&bzip2_accel, 0); return ret; } dfx-mgr-xilinx_v2023.2/example/sys/linux/dfx-mgr-client.c000066400000000000000000000316031446677152000233420ustar00rootroot00000000000000/* * Copyright (c) 2021, Xilinx Inc. and Contributors. All rights reserved. * * SPDX-License-Identifier: MIT */ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include int main(int argc, char *argv[]) { socket_t gs; struct message send_message, recv_message; int ret; memset (&send_message, '\0', sizeof(struct message)); memset (&recv_message, '\0', sizeof(struct message)); if (argc < 2) { printf("Expects an argument. Use -h to see options\n"); return -1; } initSocket(&gs); if (!strcmp(argv[1],"-load")) { if (argc < 3) { printf("-load expects a package name. Try again.\n"); return -1; } memcpy(send_message.data, argv[2], strlen(argv[2])); send_message.id = LOAD_ACCEL; send_message.size = strlen(argv[2]); if (write(gs.sock_fd, &send_message, HEADERSIZE + send_message.size) < 0){ perror("write"); return -1; } ret = read(gs.sock_fd, &recv_message, sizeof (struct message)); if (ret <= 0){ perror("No message or read error"); return -1; } printf("%s: %s %s\n", argv[2], recv_message.data[0] == '-' ? "load Error:" : "loaded to slot", recv_message.data); } else if(!strcmp(argv[1],"-remove")) { /* If no slot number provided default to 0*/ char *slot = (argc < 3) ? "0" : argv[2]; send_message.size = 1 + sprintf(send_message.data, "%s", slot); send_message.id = REMOVE_ACCEL; if (write(gs.sock_fd, &send_message, HEADERSIZE + send_message.size) < 0){ perror("write"); return -1; } ret = read(gs.sock_fd, &recv_message, sizeof (struct message)); if (ret <= 0){ perror("No message or read error"); return -1; } printf("remove from slot %s returns: %s (%s)\n", slot, recv_message.data, recv_message.data[0] == '0' ? "Ok" : "Error"); } else if(!strcmp(argv[1],"-listPackage")) { send_message.id = LIST_PACKAGE; send_message.size = 0; if (write(gs.sock_fd, &send_message, HEADERSIZE + send_message.size) == -1){ perror("write"); return -1; } ret = read(gs.sock_fd, &recv_message, sizeof (struct message)); if (ret <= 0){ perror("No message or read error"); return -1; } printf("%s",recv_message.data); } else if(!strcmp(argv[1],"-listUIO")) { /* * Need to convert to getopt_long. If argc=2, use slot 0. * No UIO name means "list all", else get the first match */ char *uio = (argc < 4) ? "" : argv[3]; send_message._u.slot = (argc == 3 || argc == 4) ? 0xff & strtol(argv[2], NULL, 10) : 0; send_message.size = 1 + sprintf(send_message.data, "%s", uio); send_message.id = LIST_ACCEL_UIO; if (write(gs.sock_fd, &send_message, HEADERSIZE + send_message.size) == -1){ perror("write"); return -1; } ret = read(gs.sock_fd, &recv_message, sizeof (struct message)); if (ret <= 0){ perror("No message or read error"); return -1; } printf("%s\n", recv_message.data); } else if (!strcmp(argv[1], "-listIRbuf")) { send_message.id = SIHA_IR_LIST; send_message.size = 0; if (write(gs.sock_fd, &send_message, HEADERSIZE + send_message.size) == -1) { perror("write"); return -1; } ret = read(gs.sock_fd, &recv_message, sizeof(struct message)); if (ret <= 0) { perror("No message or read error"); return -1; } printf("%s\n", recv_message.data); } else if (!strcmp(argv[1], "-setIRbuf")) { if (argc < 3) { printf("-setIRbuf expects slot/accelerator list\n"); return -1; } send_message.id = SIHA_IR_SET; send_message.size = strlen(argv[2]); memcpy(send_message.data, argv[2], send_message.size); if (write(gs.sock_fd, &send_message, HEADERSIZE + send_message.size) == -1) { perror("write"); return -1; } ret = read(gs.sock_fd, &recv_message, sizeof(struct message)); if (ret <= 0) { perror("No message or read error"); return -1; } printf("%s\n", recv_message.data); } else if(!strcmp(argv[1],"-allocBuffer")) { } else if(!strcmp(argv[1],"-freeBuffer")) { } else if(!strcmp(argv[1],"-getFDs")) { } else if(!strcmp(argv[1],"-getRMInfo")) { } else if(!strcmp(argv[1],"-getShellFD")) { } else if(!strcmp(argv[1],"-getClockFD")) { } else if(!strcmp(argv[1],"-h") || !strcmp(argv[1],"--help")) { printf("Usage dfx-mgr-client COMMAND\n"); printf("Commmands\n"); printf("-listPackage\t\t List locally downloaded accelerator package\n"); printf("-load \t\t Load the provided accelerator packaged\n"); printf("-remove \t\t Unload package previously programmed\n"); printf("-listUIO [ [UIOname]]\t\t list accelerator UIOs\n"); printf("-listIRbuf [slot]\t\t list inter-RM buffer info\n"); printf("-setIRbuf a,b\t\t set RM stream from slot a to b\n"); printf("-allocBuffer \t\t Allocate buffer of size and return its DMA fd and pa\n"); printf("-freeBuffer \t\t free buffer with physical address pa in decimal\n"); printf("-getFDs \t\t Send ip device FD's over socket\n"); printf("-getRMInfo \n"); printf("-getShellFD \n"); printf("-getClockFD \n"); } else { printf("Option not recognized, Try again.\n"); } return 0; } /* #include #include #include #include #include static int interrupted; static struct lws *web_socket; static const char *arg; static const char *cmd; struct pss { char body_part; }; struct msg{ char cmd[32]; char arg[32]; }; struct resp{ char data[4096]; int len; }; static int msgs_sent; #define EXAMPLE_RX_BUFFER_BYTES (sizeof(struct resp)) struct payload { unsigned char data[LWS_SEND_BUFFER_PRE_PADDING + EXAMPLE_RX_BUFFER_BYTES + LWS_SEND_BUFFER_POST_PADDING]; size_t len; } received_payload; static int callback_example( struct lws *wsi, enum lws_callback_reasons reason, void *user, void *in, size_t len ) { struct msg *m; struct resp *r; switch( reason ) { case LWS_CALLBACK_CLIENT_ESTABLISHED: lwsl_debug("LWS_CALLBACK_CLIENT_ESTABLISHED user %s\n",(char *)user); lws_callback_on_writable( wsi ); break; case LWS_CALLBACK_CLIENT_RECEIVE: lwsl_debug("LWS_CALLBACK_CLIENT_RECEIVE len %ld\n",len); msgs_sent--; memcpy( &received_payload.data[LWS_SEND_BUFFER_PRE_PADDING], in, len ); received_payload.len = len; r = (struct resp *)&received_payload.data[LWS_SEND_BUFFER_PRE_PADDING]; lwsl_debug("client recieved %s len %d\n",r->data,r->len); if(!msgs_sent) interrupted = 1; break; case LWS_CALLBACK_CLIENT_WRITEABLE: lwsl_debug("LWS_CALLBACK_CLIENT_WRITEABLE len %ld cmd %s \n",len,cmd); unsigned char buf[LWS_SEND_BUFFER_PRE_PADDING + sizeof(struct msg) + LWS_SEND_BUFFER_POST_PADDING]; //unsigned char *p = &buf[LWS_SEND_BUFFER_PRE_PADDING]; //size_t n = sprintf( (char *)p, "%u", rand() ); m = (struct msg *)&buf[LWS_SEND_BUFFER_PRE_PADDING]; sprintf(m->cmd,"%s",cmd); sprintf(m->arg,"%s",arg); lws_write( wsi, (unsigned char *)m, sizeof(struct msg), LWS_WRITE_TEXT ); if(strcmp(cmd,"-loadpdi")) interrupted = 1; //lws_cancel_service(lws_get_context(wsi)); msgs_sent++; break; case LWS_CALLBACK_CLOSED: lwsl_debug("LWS_CALLBACK_CLOSED\n"); interrupted = 1; break; case LWS_CALLBACK_CLIENT_CONNECTION_ERROR: lwsl_err("CLIENT_CONNECTION_ERROR: %s\n", in ? (char *)in : "(null)"); interrupted = 1; break; default: break; } return lws_callback_http_dummy(wsi, reason, user, in, len); } static int callback_http(struct lws *wsi, enum lws_callback_reasons reason, void *user, void *in, size_t len) { struct pss *pss = (struct pss *)user; char buf[LWS_SEND_BUFFER_PRE_PADDING + 1024]; char *start = &buf[LWS_SEND_BUFFER_PRE_PADDING]; char *p = start; char *end = &buf[sizeof(buf) - LWS_SEND_BUFFER_PRE_PADDING -1]; int n; switch (reason) { case LWS_CALLBACK_CLIENT_CONNECTION_ERROR: lwsl_user("CLIENT_CONNECTION_ERROR: %s\n", in ? (char *)in : "(null)"); interrupted = 1; break; case LWS_CALLBACK_CLIENT_APPEND_HANDSHAKE_HEADER: if (!lws_http_is_redirected_to_get(wsi)) { lwsl_user("doing POST flow\n"); lws_client_http_body_pending(wsi, 1); lws_callback_on_writable(wsi); } else lwsl_user("doing GET flow\n"); break; case LWS_CALLBACK_CLIENT_HTTP_WRITEABLE: lwsl_user("LWS_CALLBACK_CLIENT_HTTP_WRITEABLE\n"); if (lws_http_is_redirected_to_get(wsi)) break; switch (pss->body_part++) { case 0: if (lws_client_http_multipart(wsi, "text1", NULL, NULL,&p,end)) return -1; p += lws_snprintf(p, end - p,"%s",arg); n = LWS_WRITE_HTTP; break; case 1: if (lws_client_http_multipart(wsi, NULL, NULL, NULL,&p,end)) return -1; lws_client_http_body_pending(wsi, 0); n = LWS_WRITE_HTTP_FINAL; break; default: return 0; } if (lws_write(wsi, (uint8_t *)start, lws_ptr_diff(p, start), n) != lws_ptr_diff(p, start)) return 1; if (n != LWS_WRITE_HTTP_FINAL) lws_callback_on_writable(wsi); return 0; case LWS_CALLBACK_COMPLETED_CLIENT_HTTP: lwsl_user("LWS_CALLBACK_COMPLETED_CLIENT_HTTP\n"); interrupted = 1; lws_cancel_service(lws_get_context(wsi)); break; case LWS_CALLBACK_CLOSED_CLIENT_HTTP: lwsl_user("LWS_CALLBACK_CLOSED_CLIENT_HTTP\n"); interrupted = 1; lws_cancel_service(lws_get_context(wsi)); break; default: break; } return lws_callback_http_dummy(wsi, reason, user, in, len); }*/ /* static struct lws_protocols protocols[] = { { "example-protocol", callback_example, 0, EXAMPLE_RX_BUFFER_BYTES, 0, NULL, 0 }, { NULL, NULL, 0, 0, 0, NULL, 0} }; static const struct lws_protocols protocols[] = { { "http", callback_http, sizeof(struct pss), 0, 0, NULL, 0 }, { NULL, NULL, 0, 0, 0, NULL, 0 } };*/ /*static void sigint_handler(int sig) { lwsl_debug("Recieved signal %d\n",sig); interrupted = 1; } int main(int argc, const char **argv) { struct lws_context_creation_info info; struct lws_context *context; struct lws_client_connect_info ccinfo = {0}; const char *option; signal(SIGINT, sigint_handler); memset(&info, 0, sizeof info); memset(&ccinfo, 0, sizeof ccinfo); lws_cmdline_option_handle_builtin(argc, argv, &info); info.port = CONTEXT_PORT_NO_LISTEN; info.protocols = protocols; info.gid = -1; info.uid = -1; //info.connect_timeout_secs = 30; context = lws_create_context(&info); if (!context) { lwsl_err("lws init failed\n"); return 1; } ccinfo.context = context; ccinfo.address = "localhost"; ccinfo.port = 7681; ccinfo.protocol = protocols[0].name; ccinfo.path = "/"; //ccinfo.ssl_connection = LCCSCF_HTTP_MULTIPART_MIME | LCCSCF_ALLOW_SELFSIGNED; if ((option = lws_cmdline_option(argc, argv, "-load"))) { cmd = "-load"; if (strcmp(option,"") == 0) { printf("-load expects a package name. Try again.\n"); return 0; } arg = option; } else if ((option = lws_cmdline_option(argc, argv, "-remove"))) { cmd = "-remove"; arg = option; } else if (lws_cmdline_option(argc, argv, "-listPackage")) { cmd = "-listPackage"; arg = ""; } else if ((option = lws_cmdline_option(argc, argv, "-allocBuffer"))) { cmd = "-allocBuffer"; arg = option; } else if ((option = lws_cmdline_option(argc, argv, "-freeBuffer"))) { cmd = "-freeBuffer"; arg = option; } else if ((option = lws_cmdline_option(argc, argv, "-getFDs"))) { cmd = "-getFDs"; arg = option; } else if ((lws_cmdline_option(argc, argv, "-getRMInfo"))) { cmd = "-getRMInfo"; arg = ""; } else if ((lws_cmdline_option(argc, argv, "-getShellFD"))) { cmd = "-getShellFD"; arg = ""; } else if ((lws_cmdline_option(argc, argv, "-getClockFD"))) { cmd = "-getClockFD"; arg = ""; } else if (lws_cmdline_option(argc, argv, "-h") || lws_cmdline_option(argc, argv, "--help")) { printf("Usage dfx-mgr-client COMMAND\n"); printf("Commmands\n"); printf("-listPackage\t\t List locally downloaded accelerator package\n"); printf("-load \t\t Load the provided accelerator packaged\n"); printf("-remove \t\t\t Unload package previously programmed\n"); printf("-allocBuffer \t\t Allocate buffer of size and return its DMA fd and pa\n"); printf("-freeBuffer \t\t free buffer with physical address pa in decimal\n"); printf("-getFDs \t\t Send ip device FD's over socket\n"); printf("-getRMInfo \n"); printf("-getShellFD \n"); printf("-getClockFD \n"); return 0; } else { printf("Option not recognized, Try again.\n"); return 0; } //ccinfo.method = "POST"; web_socket = lws_client_connect_via_info(&ccinfo); lwsl_debug("http client started\n"); while (!interrupted) if(lws_service(context, 0)) interrupted = 1; lws_context_destroy(context); return 0; }*/ dfx-mgr-xilinx_v2023.2/example/sys/linux/dfx-mgrd.c000066400000000000000000000300571446677152000222340ustar00rootroot00000000000000/* * Copyright (c) 2021, Xilinx Inc. and Contributors. All rights reserved. * * SPDX-License-Identifier: MIT */ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #define MAX_CLIENTS 200 static volatile int interrupted = 0; static int socket_d; void intHandler(int dummy) { _unused(dummy); interrupted = 1; exit(EXIT_SUCCESS); } void dfx_exit(char *msg) { DFX_ERR("%s", msg); exit(EXIT_FAILURE); } static void process_dfx_req(int fd, fd_set *fdset) { struct message recv_msg, send_msg; ssize_t numbytes; int ret, slot; numbytes = read(fd, &recv_msg, sizeof(struct message)); if (numbytes <= 0) { if (numbytes < 0) DFX_ERR("read(%d)", fd); else DFX_DBG("Socket %d closed by client", fd); if (close(fd) == -1) DFX_ERR("close(%d)", fd); FD_CLR(fd, fdset); return; } // data from client memset(&send_msg, 0, sizeof(struct message)); switch (recv_msg.id) { case LOAD_ACCEL: DFX_PR("daemon loading accel %s", recv_msg.data); slot = load_accelerator(recv_msg.data); send_msg.size = 1 + sprintf(send_msg.data, "%d", slot); if (write(fd, &send_msg, HEADERSIZE + send_msg.size) < 0) DFX_ERR("LOAD_ACCEL write(%d)", fd); break; case REMOVE_ACCEL: slot = -1; /* assume base */ if (strcasecmp(recv_msg.data, "base")) { slot = atoi(recv_msg.data); DFX_PR("daemon REMOVE_ACCEL in slot %d", slot); } ret = remove_accelerator(slot); send_msg.size = 1 + sprintf(send_msg.data, "%d", ret); if (write(fd, &send_msg, HEADERSIZE+ send_msg.size) < 0) DFX_ERR("REMOVE_ACCEL write(%d)", fd); break; case LIST_PACKAGE: // change to: listAccelerators(buf, size)) char *msg = listAccelerators(); send_msg.size = strnlen(msg, sizeof(send_msg.data)); memcpy(send_msg.data, msg, send_msg.size); if (write(fd, &send_msg, HEADERSIZE + send_msg.size) < 0) DFX_ERR("LIST_PACKAGE write(%d)", fd); free(msg); break; case LIST_ACCEL_UIO: /* slot = atoi(recv_msg.data); */ slot = recv_msg._u.slot; if (recv_msg.data[0] == 0) list_accel_uio(slot, send_msg.data, sizeof(send_msg.data)); else { char *p = get_accel_uio_by_name(slot, recv_msg.data); DFX_DBG("%s", recv_msg.data); if (p != NULL) sprintf(send_msg.data, "%s", p); } send_msg.size = strnlen(send_msg.data, sizeof(send_msg.data)); if (write(fd, &send_msg, HEADERSIZE + send_msg.size) < 0) DFX_ERR("LIST_ACCEL_UIO write(%d)", fd); break; case SIHA_IR_LIST: ret = siha_ir_buf_list(sizeof(send_msg.data), send_msg.data); /* * The siha_ir_buf_list returns 0 on error or the size of * the buffer. The (ret < 0) check is to avoid a large * (e.g: 4GB = unsigned(-1)) write request. */ send_msg.size = ret < 0 ? 0 : ret; if (write(fd, &send_msg, HEADERSIZE + send_msg.size) < 0) DFX_ERR("SIHA_IR_LIST: write(%d)", fd); break; case SIHA_IR_SET: ret = siha_ir_buf_set(recv_msg.data); send_msg.size = 1 + sprintf(send_msg.data, "%d SIHA_IR_SET: %.18s", ret, recv_msg.data); if (write(fd, &send_msg, HEADERSIZE + send_msg.size) < 0) DFX_ERR("SIHA_IR_SET: write(%d)", fd); break; case QUIT: if (close(fd) == -1) DFX_ERR("close(%d)", fd); FD_CLR(fd, fdset); break; default: send_msg.size = 1 + sprintf(send_msg.data, "Unsupported message id %d", recv_msg.id); if (write(fd, &send_msg, HEADERSIZE + send_msg.size) < 0) DFX_ERR("default write(%d)", fd); DFX_PR("%s", send_msg.data); } } int main(int argc, char **argv) { const struct sockaddr_un su = { .sun_family = AF_UNIX, .sun_path = SERVER_SOCKET, }; struct stat statbuf; fd_set fds, readfds; int fd_new, fdmax; signal(SIGINT, intHandler); _unused(argc); _unused(argv); // initialize the complaint queue dfx_init(); if (stat(SERVER_SOCKET, &statbuf) == 0) { if (unlink(SERVER_SOCKET) == -1) dfx_exit("unlink " SERVER_SOCKET); } if ((socket_d = socket(AF_UNIX, SOCK_SEQPACKET, 0)) == -1) dfx_exit("socket"); if (bind(socket_d, (const struct sockaddr *)&su, sizeof(su)) == -1) dfx_exit("bind"); // Mark socket for accepting incoming connections using accept if (listen(socket_d, BACKLOG) == -1) dfx_exit("listen"); FD_ZERO(&fds); FD_SET(socket_d, &fds); fdmax = socket_d; DFX_PR("dfx-mgr daemon started"); while (1) { readfds = fds; // monitor readfds for readiness for reading if (select(fdmax + 1, &readfds, NULL, NULL, NULL) == -1) dfx_exit("select"); // Some sockets are ready. Examine readfds for (int fd = 0; fd < (fdmax + 1); fd++) { if (FD_ISSET(fd, &readfds)) { // fd is ready for reading if (fd == socket_d) { // request for new connection fd_new = accept(socket_d, NULL, NULL); if (fd_new == -1) dfx_exit("accept"); FD_SET(fd_new, &fds); if (fd_new > fdmax) fdmax = fd_new; } else { // data from an existing connection process_dfx_req(fd, &fds); } } } } exit(EXIT_SUCCESS); } /* #define SERVER_PATH "/tmp/dfx-mgrd_socket" static int interrupted;; static int socket_d; // struct pss { struct lws_spa *spa; }; */ /*static const char * const param_names[] = { "text1", }; enum enum_param_names { EPN_TEXT1, };*/ /*struct msg{ char cmd[32]; char arg[128]; }; struct resp{ char data[4096]; int len; }; #define EXAMPLE_RX_BUFFER_BYTES sizeof(struct msg) struct payload { unsigned char data[LWS_SEND_BUFFER_PRE_PADDING + EXAMPLE_RX_BUFFER_BYTES + LWS_SEND_BUFFER_POST_PADDING]; size_t len; } received_payload; unsigned char buf[LWS_SEND_BUFFER_PRE_PADDING + sizeof(struct resp) + LWS_SEND_BUFFER_POST_PADDING]; static int msgs; static int callback_example( struct lws *wsi, enum lws_callback_reasons reason, void *user, void *in, size_t len ) { struct msg *m = (struct msg*)malloc(sizeof(struct msg)); struct resp *r = (struct resp *)&buf[LWS_SEND_BUFFER_PRE_PADDING]; int slot; switch( reason ) { case LWS_CALLBACK_ESTABLISHED: lwsl_user("LWS_CALLBACK_ESTABLISHED user %s\n",(char *)user); break; case LWS_CALLBACK_RECEIVE: acapd_debug("LWS_CALLBACK_RECEIVE len%ld\n",len); memcpy( &received_payload.data[LWS_SEND_BUFFER_PRE_PADDING], in, len ); received_payload.len = len; m = (struct msg *)&received_payload.data[LWS_SEND_BUFFER_PRE_PADDING]; acapd_debug("server received cmd %s arg %s\n",m->cmd,m->arg); msgs++; if(strcmp(m->cmd,"-load") == 0){ lwsl_debug("Received %s \n",m->cmd); slot = load_accelerator(m->arg); sprintf(r->data,"%d",slot); r->len = 1; acapd_debug("daemon: load done slot %s len %d\n", r->data, r->len); lws_callback_on_writable_all_protocol( lws_get_context( wsi ), lws_get_protocol( wsi ) ); } else if(strcmp(m->cmd,"-remove") == 0){ lwsl_debug("Received %s slot %s\n",m->cmd,m->arg); r->len = 0; remove_accelerator(atoi(m->arg)); lws_callback_on_writable_all_protocol( lws_get_context( wsi ), lws_get_protocol( wsi ) ); } else if(strcmp(m->cmd,"-allocBuffer") == 0){ lwsl_debug("Received %s size %s\n",m->cmd,m->arg); sendBuff(atoi(m->arg)); sprintf(r->data,"%s",""); r->len = 0; lws_callback_on_writable( wsi ); } else if(strcmp(m->cmd,"-freeBuffer") == 0){ lwsl_debug("Received %s size %s\n",m->cmd,m->arg); freeBuff(atoi(m->arg)); sprintf(r->data,"%s",""); r->len = 0; lws_callback_on_writable(wsi); } else if(strcmp(m->cmd,"-getShellFD") == 0){ lwsl_debug("Received %s \n",m->cmd); sprintf(r->data,"%s",""); r->len = 0; getShellFD(); lws_callback_on_writable_all_protocol( lws_get_context( wsi ), lws_get_protocol( wsi ) ); } else if(strcmp(m->cmd,"-getClockFD") == 0){ lwsl_debug("Received %s \n",m->cmd); sprintf(r->data,"%s",""); r->len = 0; getClockFD(); lws_callback_on_writable_all_protocol( lws_get_context( wsi ), lws_get_protocol( wsi ) ); } else if(strcmp(m->cmd,"-getFDs") == 0){ lwsl_debug("Received %s slot %s\n",m->cmd,m->arg); sprintf(r->data,"%s",""); r->len = 0; getFDs(atoi(m->arg)); lws_callback_on_writable(wsi); } else if(strcmp(m->cmd,"-listPackage") == 0){ lwsl_debug("Received -listPackage\n"); sprintf(r->data,"%s",""); r->len = 0; listAccelerators(); lws_callback_on_writable_all_protocol( lws_get_context( wsi ), lws_get_protocol( wsi ) ); } else { lwsl_err("cmd not recognized\n"); //return -1; } break; case LWS_CALLBACK_SERVER_WRITEABLE: if (!msgs) return 0; lwsl_debug("LWS_CALLBACK_SERVER_WRITEABLE resp->len %d\n",r->len); lws_write( wsi, (unsigned char*)r, sizeof(struct resp), LWS_WRITE_TEXT ); msgs--; //return -1; break; default: break; } return 0; } enum protocols { PROTOCOL_HTTP = 0, PROTOCOL_EXAMPLE, PROTOCOL_COUNT }; static const struct lws_protocols protocols[] = { // first protocol must always be HTTP handler { "http", lws_callback_http_dummy, 0, 0, 0, NULL, 0, }, { "example-protocol", callback_example, 0, EXAMPLE_RX_BUFFER_BYTES, 0, NULL, 0, }, { NULL, NULL, 0, 0, 0, NULL, 0 } }; void sigint_handler(int sig) { lwsl_err("server interrupted signal %d \n",sig); interrupted = 1; } void socket_fd_setup() { struct sockaddr_un serveraddr; if (access(SERVER_PATH, F_OK) == 0) unlink(SERVER_PATH); socket_d = socket(AF_UNIX, SOCK_STREAM, 0); if (socket_d < 0) { acapd_perror("%s socket creation failed\n",__func__); //return ACAPD_ACCEL_FAILURE; } memset(&serveraddr, 0, sizeof(serveraddr)); serveraddr.sun_family = AF_UNIX; strcpy(serveraddr.sun_path, SERVER_PATH); if (bind(socket_d, (struct sockaddr *)&serveraddr, SUN_LEN(&serveraddr))) { acapd_perror("%s socket bind() failed\n",__func__); //return ACAPD_ACCEL_FAILURE; } acapd_debug("%s socket bind done\n",__func__); //socket will queue upto 10 incoming connections if (listen(socket_d, 10)) { acapd_perror("%s socket listen() failed\n",__func__); //return ACAPD_ACCEL_FAILURE; } printf("Server started %s ready for client connect.\n", SERVER_PATH); } int main(int argc, const char **argv) { struct lws_context_creation_info info; struct lws_context *context; struct daemon_config config; pthread_t t; const char *p; int n = 0, logs = LLL_ERR | LLL_WARN // for LLL_ verbosity above NOTICE to be built into lws, // lws must have been configured and built with // -DCMAKE_BUILD_TYPE=DEBUG instead of =RELEASE // | LLL_INFO */ /* | LLL_PARSER */ /* | LLL_HEADER // | LLL_EXT */ /* | LLL_CLIENT */ /* | LLL_LATENCY // | LLL_DEBUG */; /* acapd_debug("Starting http daemon\n"); signal(SIGINT, sigint_handler); if ((p = lws_cmdline_option(argc, argv, "-d"))) logs = atoi(p); lws_set_log_level(logs, NULL); lwsl_user("LWS minimal http server dynamic | visit http://localhost:7681\n"); memset(&info, 0, sizeof info); //info.options = LWS_SERVER_OPTION_DO_SSL_GLOBAL_INIT | // LWS_SERVER_OPTION_EXPLICIT_VHOSTS | // LWS_SERVER_OPTION_HTTP_HEADERS_SECURITY_BEST_PRACTICES_ENFORCE; info.port = 7681; info.protocols = protocols; info.gid = -1; info.uid = -1; info.vhost_name = "localhost"; info.options = LWS_SERVER_OPTION_HTTP_HEADERS_SECURITY_BEST_PRACTICES_ENFORCE; context = lws_create_context(&info); if (!context) { lwsl_err("lws init failed\n"); return 1; } if (!lws_create_vhost(context, &info)) { lwsl_err("Failed to create tls vhost\n"); goto bail; } sem_init(&mutex, 0, 0); pthread_create(&t, NULL,threadFunc, NULL); socket_fd_setup(); while (n >= 0 && !interrupted) n = lws_service(context, 0); bail: lws_context_destroy(context); return 0; }*/ dfx-mgr-xilinx_v2023.2/example/sys/linux/graph/000077500000000000000000000000001446677152000214545ustar00rootroot00000000000000dfx-mgr-xilinx_v2023.2/example/sys/linux/graph/CMakeLists.txt000066400000000000000000000032051446677152000242140ustar00rootroot00000000000000######################################################################### # Copyright (c) 2021, Xilinx Inc. and Contributors. All rights reserved. # SPDX-License-Identifier: MIT ######################################################################### collector_list (_list PROJECT_INC_DIRS) include_directories (${_list} ${CMAKE_CURRENT_SOURCE_DIR}) collector_list (_list PROJECT_LIB_DIRS) link_directories (${_list}) SET(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -pthread") set (_deps "dfx" "dfxgraph" "dl" "pthread") foreach (_app graphApp graphTest0 graphTest1 graphTest2 graphTest3 graphTest4 graphTest5) set (_src ${CMAKE_CURRENT_SOURCE_DIR}/${_app}.c) if (WITH_SHARED_LIB) add_executable (${_app}-share ${_src}) if (PROJECT_EC_FLAGS) string(REPLACE " " ";" _ec_flgs ${PROJECT_EC_FLAGS}) target_compile_options (${_app}-share PUBLIC ${_ec_flgs}) endif (PROJECT_EC_FLAGS) target_link_libraries (${_app}-share ${PROJECT_NAME}-shared ${_deps}) install (TARGETS ${_app}-share RUNTIME DESTINATION bin) add_dependencies (${_app}-share ${PROJECT_NAME}-shared) endif (WITH_SHARED_LIB) if (WITH_STATIC_LIB) if (${PROJECT_SYSTEM} STREQUAL "linux") add_executable (${_app}-static ${_src}) if (PROJECT_EC_FLAGS) string(REPLACE " " ";" _ec_flgs ${PROJECT_EC_FLAGS}) target_compile_options (${_app}-static PUBLIC ${_ec_flgs}) endif (PROJECT_EC_FLAGS) target_link_libraries (${_app}-static ${PROJECT_NAME}-static ${_deps}) install (TARGETS ${_app}-static RUNTIME DESTINATION bin) endif (${PROJECT_SYSTEM} STREQUAL "linux") endif (WITH_STATIC_LIB) endforeach (_app) dfx-mgr-xilinx_v2023.2/example/sys/linux/graph/graphApp.c000066400000000000000000000646531446677152000234000ustar00rootroot00000000000000/* * Copyright (c) 2021, Xilinx Inc. and Contributors. All rights reserved. * * SPDX-License-Identifier: MIT */ #include #include #include #include #include #include //#include #include //#include "metadata.h" #include #include #include #include uint32_t buff[] = { 0xcca5a729, 0x4b276e90, 0x9a57a7e7, 0xd0bfe1c7, 0xcca5a729, 0x4b276e90, 0x9a57a7e7, 0xd0bfe1c7, 0xcca5a729, 0x4b276e90, 0x9a57a7e7, 0xd0bfe1c7, 0xcca5a729, 0x4b276e90, 0x9a57a7e7, 0xd0bfe1c7, 0xcca5a729, 0x4b276e90, 0x9a57a7e7, 0xd0bfe1c7, 0xcca5a729, 0x4b276e90, 0x9a57a7e7, 0xd0bfe1c7, 0xcca5a729, 0x4b276e90, 0x9a57a7e7, 0xd0bfe1c7, 0xcca5a729, 0x4b276e90, 0x9a57a7e7, 0xd0bfe1c7, 0xcca5a729, 0x4b276e90, 0x9a57a7e7, 0xd0bfe1c7, 0xcca5a729, 0x4b276e90, 0x9a57a7e7, 0xd0bfe1c7, 0xcca5a729, 0x4b276e90, 0x9a57a7e7, 0xd0bfe1c7, 0xcca5a729, 0x4b276e90, 0x9a57a7e7, 0xd0bfe1c7, 0xcca5a729, 0x4b276e90, 0x9a57a7e7, 0xd0bfe1c7, 0xcca5a729, 0x4b276e90, 0x9a57a7e7, 0xd0bfe1c7, 0xcca5a729, 0x4b276e90, 0x9a57a7e7, 0xd0bfe1c7, 0xcca5a729, 0x4b276e90, 0x9a57a7e7, 0xd0bfe1c7, 0xcca5a729, 0x4b276e90, 0x9a57a7e7, 0xd0bfe1c7 }; uint32_t keybuff[] = { 0x0c0d0e0f, 0x08090a0b, 0x04050607, 0x00010203, 0x00000000, 0x00000000, 0x00000000, 0x00000000 }; int softFFT(void* inData, int inDataSize, void* inConfig, int inConfigSize, void* outData, int outDataSize){ INFO("FALLBACK CALLED !!\n"); _unused(inConfig); _unused(inConfigSize); _unused(outDataSize); memcpy(outData, inData, inDataSize); return 0; } int softFIR(void* inData, int inDataSize, void* inConfig, int inConfigSize, void* outData, int outDataSize){ INFO("FALLBACK CALLED !!\n"); _unused(inConfig); _unused(inConfigSize); _unused(outDataSize); memcpy(outData, inData, inDataSize); return 0; } int softAES128(void* inData, int inDataSize, void* inConfig, int inConfigSize, void* outData, int outDataSize){ INFO("FALLBACK CALLED !!\n"); _unused(inConfig); _unused(inConfigSize); _unused(outDataSize); memcpy(outData, inData, inDataSize); return 0; } #define BUFFSIZE 0x400000 int case0(){ INFO("TEST0: Just load CMA buffer without PL Accelerator"); AbstractGraph_t *acapGraph = graphInit(); AbstractAccelNode_t *accelNode0 = addInputNode(acapGraph, 32*1024*1024); AbstractAccelNode_t *accelNode1 = addOutputNode(acapGraph, 32*1024*1024); _unused(accelNode0); _unused(accelNode1); abstractGraphConfig(acapGraph); for(int i=0; i < 1024; i++){ accelNode0->ptr[i] = i; } //printhex((uint32_t*)accelNode0->ptr, 0x50); //printhex((uint32_t*)accelNode1->ptr, 0x50); abstractGraphFinalise(acapGraph); return 0; } int case1(){ int status; INFO("TEST1: Load CMA buffer without PL Accelerator and test transactions\n"); AbstractGraph_t *acapGraph = graphInit(); AbstractAccelNode_t *accelNode0 = addInputNode(acapGraph, 32*1024*1024); AbstractAccelNode_t *accelNode1 = addOutputNode(acapGraph, 32*1024*1024); AbstractBuffNode_t *buffNode0 = addBuffer(acapGraph, 16*1024*1024, DDR_BASED); addOutBuffer(acapGraph, accelNode0, buffNode0, 0x00, 32*1024*1024, 1, 0); addInBuffer (acapGraph, accelNode1, buffNode0, 0x00, 32*1024*1024, 2, 0); status = abstractGraphConfig(acapGraph); if(status < 0){ printf("Seems like GraphDaemon not running ...!!\n"); return -1; } for(int i=0; i < 1024; i++){ accelNode0->ptr[i] = i; } sem_post(accelNode0->semptr); sem_wait(accelNode1->semptr); printhex((uint32_t*)accelNode0->ptr, 0x50); printhex((uint32_t*)accelNode1->ptr, 0x50); abstractGraphFinalise(acapGraph); return 0; } int case2(){ int status; INFO("TEST1: CMA buffer with single PL Accelerator\n"); AbstractGraph_t *acapGraph = graphInit(); AbstractAccelNode_t *accelNode0 = addInputNode(acapGraph, 32*1024*1024); AbstractAccelNode_t *accelNode1 = addAcceleratorNode(acapGraph, "FFT4"); AbstractAccelNode_t *accelNode2 = addOutputNode(acapGraph, 32*1024*1024); AbstractBuffNode_t *buffNode0 = addBuffer(acapGraph, 16*1024*1024, DDR_BASED); AbstractBuffNode_t *buffNode1 = addBuffer(acapGraph, 16*1024*1024, DDR_BASED); addOutBuffer(acapGraph, accelNode0, buffNode0, 0x00, 32*1024*1024, 1, 0); addInBuffer (acapGraph, accelNode1, buffNode0, 0x00, 32*1024*1024, 2, 0); addOutBuffer(acapGraph, accelNode1, buffNode1, 0x00, 32*1024*1024, 2, 0); addInBuffer (acapGraph, accelNode2, buffNode1, 0x00, 32*1024*1024, 3, 0); status = abstractGraphConfig(acapGraph); if(status < 0){ printf("Seems like GraphDaemon not running ...!!\n"); return -1; } for(int i=0; i < 1024; i++){ accelNode0->ptr[i] = i; } sem_post(accelNode0->semptr); sem_wait(accelNode2->semptr); printhex((uint32_t*)accelNode0->ptr, 0x50); printhex((uint32_t*)accelNode2->ptr, 0x50); abstractGraphFinalise(acapGraph); return 0; } int case3(){ int status; INFO("TEST3: Test Accel Chain\n"); AbstractGraph_t *acapGraph = graphInit(); AbstractAccelNode_t *accelNode0 = addInputNode(acapGraph, 32*1024*1024); AbstractAccelNode_t *accelNode1 = addAcceleratorNode(acapGraph, "fir_compiler"); AbstractAccelNode_t *accelNode2 = addAcceleratorNode(acapGraph, "FFT4"); AbstractAccelNode_t *accelNode3 = addAcceleratorNode(acapGraph, "aes128encdec"); AbstractAccelNode_t *accelNode4 = addOutputNode(acapGraph, 32*1024*1024); AbstractAccelNode_t *accelNode5 = addOutputNode(acapGraph, 32*1024*1024); AbstractBuffNode_t *buffNode0 = addBuffer(acapGraph, 16*1024*1024, DDR_BASED); AbstractBuffNode_t *buffNode1 = addBuffer(acapGraph, 16*1024*1024, DDR_BASED); AbstractBuffNode_t *buffNode2 = addBuffer(acapGraph, 16*1024*1024, DDR_BASED); AbstractBuffNode_t *buffNode3 = addBuffer(acapGraph, 16*1024*1024, DDR_BASED); addOutBuffer(acapGraph, accelNode0, buffNode0, 0x00, 32*1024*1024, 1, 0); addInBuffer (acapGraph, accelNode1, buffNode0, 0x00, 32*1024*1024, 2, 0); addOutBuffer(acapGraph, accelNode1, buffNode1, 0x00, 32*1024*1024, 2, 0); addInBuffer (acapGraph, accelNode2, buffNode0, 0x00, 32*1024*1024, 3, 0); addOutBuffer(acapGraph, accelNode2, buffNode2, 0x00, 32*1024*1024, 3, 0); addInBuffer (acapGraph, accelNode3, buffNode1, 0x00, 32*1024*1024, 4, 0); addOutBuffer(acapGraph, accelNode3, buffNode3, 0x00, 32*1024*1024, 4, 0); addInBuffer (acapGraph, accelNode4, buffNode2, 0x00, 32*1024*1024, 5, 0); addInBuffer (acapGraph, accelNode5, buffNode3, 0x00, 32*1024*1024, 6, 0); status = abstractGraphConfig(acapGraph); if(status < 0){ printf("Seems like GraphDaemon not running ...!!\n"); return -1; } for(int i=0; i < 1024; i++){ accelNode0->ptr[i] = i; } sem_post(accelNode0->semptr); printf("###\n"); sem_wait(accelNode4->semptr); printf("###\n"); sem_wait(accelNode5->semptr); printf("###\n"); printhex((uint32_t*)accelNode0->ptr, 0x50); printhex((uint32_t*)accelNode4->ptr, 0x50); printhex((uint32_t*)accelNode5->ptr, 0x50); abstractGraphFinalise(acapGraph); return 0; } /* int case3(){ INFO("TEST1: CMA buffer with single PL Accelerator\n"); uint8_t *p0 = (uint8_t*) malloc(32*1024*1024); uint8_t *p1 = (uint8_t*) malloc(32*1024*1024); AcapGraph_t *acapGraph = acapGraphInit(); AccelNode_t *accelNode0 = acapAddInputNode(acapGraph, p0, 32*1024*1024, ENABLE_SCHEDULER); AccelNode_t *accelNode1 = acapAddAccelNode(acapGraph, "fir_compiler", HLS_MULTICHANNEL_DMA, NULL, INTER_RM_NOT_COMPATIBLE, ENABLE_SCHEDULER); AccelNode_t *accelNode2 = acapAddAccelNode(acapGraph, "FFT4", HLS_MULTICHANNEL_DMA, softFFT, INTER_RM_NOT_COMPATIBLE, ENABLE_SCHEDULER); AccelNode_t *accelNode3 = acapAddAccelNode(acapGraph, "aes128encdec", HLS_MULTICHANNEL_DMA, softFFT, INTER_RM_NOT_COMPATIBLE, ENABLE_SCHEDULER); AccelNode_t *accelNode5 = acapAddOutputNode(acapGraph, p1, 32*1024*1024, ENABLE_SCHEDULER); BuffNode_t *buffNode0 = acapAddBuffNode(acapGraph, 16*1024*1024, "Buffer", DDR_BASED); BuffNode_t *buffNode1 = acapAddBuffNode(acapGraph, 16*1024*1024, "Buffer", DDR_BASED); BuffNode_t *buffNode2 = acapAddBuffNode(acapGraph, 16*1024*1024, "Buffer", DDR_BASED); BuffNode_t *buffNode3 = acapAddBuffNode(acapGraph, 16*1024*1024, "Buffer", DDR_BASED); acapAddOutputBuffer(acapGraph, accelNode0, buffNode0, 0x00, 32*1024*1024, 1, 0); acapAddInputBuffer (acapGraph, accelNode1, buffNode0, 0x00, 32*1024*1024, 2, 0); acapAddOutputBuffer(acapGraph, accelNode1, buffNode1, 0x00, 32*1024*1024, 2, 0); acapAddInputBuffer (acapGraph, accelNode2, buffNode1, 0x00, 32*1024*1024, 3, 0); acapAddOutputBuffer(acapGraph, accelNode2, buffNode2, 0x00, 32*1024*1024, 3, 0); acapAddInputBuffer (acapGraph, accelNode3, buffNode2, 0x00, 32*1024*1024, 4, 0); acapAddOutputBuffer(acapGraph, accelNode3, buffNode3, 0x00, 32*1024*1024, 4, 0); acapAddInputBuffer (acapGraph, accelNode5, buffNode3, 0x00, 32*1024*1024, 6, 0); acapGraphToJson(acapGraph); acapGraphConfig(acapGraph); acapGraphToJson(acapGraph); for(int i=0; i < 1024; i++){ p0[i] = i; } printhex((uint32_t*)p0, 0x50); acapGraphSchedule(acapGraph); printhex((uint32_t*)p1, 0x50); acapGraphFinalise(acapGraph); return 0; } int case4(){ INFO("TEST1: CMA buffer with single PL Accelerator\n"); uint8_t *p0 = (uint8_t*) malloc(64*1024*1024); uint8_t *p1 = (uint8_t*) malloc(64*1024*1024); AcapGraph_t *acapGraph = acapGraphInit(); AccelNode_t *accelNode0 = acapAddInputNode(acapGraph, p0, 64*1024*1024, ENABLE_SCHEDULER); AccelNode_t *accelNode1 = acapAddAccelNode(acapGraph, "fir_compiler", HLS_MULTICHANNEL_DMA, softFIR, INTER_RM_COMPATIBLE, ENABLE_SCHEDULER); AccelNode_t *accelNode2 = acapAddAccelNode(acapGraph, "FFT4", HLS_MULTICHANNEL_DMA, softFFT, INTER_RM_COMPATIBLE, ENABLE_SCHEDULER); AccelNode_t *accelNode3 = acapAddAccelNode(acapGraph, "aes128encdec", HLS_MULTICHANNEL_DMA, softFFT, INTER_RM_COMPATIBLE, ENABLE_SCHEDULER); AccelNode_t *accelNode4 = acapAddOutputNode(acapGraph, p1, 64*1024*1024, ENABLE_SCHEDULER); BuffNode_t *buffNode0 = acapAddBuffNode(acapGraph, 16*1024*1024, "Buffer", DDR_BASED); BuffNode_t *buffNode1 = acapAddBuffNode(acapGraph, 16*1024*1024, "Buffer", PL_BASED); BuffNode_t *buffNode2 = acapAddBuffNode(acapGraph, 16*1024*1024, "Buffer", PL_BASED); BuffNode_t *buffNode3 = acapAddBuffNode(acapGraph, 16*1024*1024, "Buffer", DDR_BASED); acapAddOutputBuffer(acapGraph, accelNode0, buffNode0, 0x00, 64*1024*1024, 1, 0); acapAddInputBuffer (acapGraph, accelNode1, buffNode0, 0x00, 64*1024*1024, 2, 0); acapAddOutputBuffer(acapGraph, accelNode1, buffNode1, 0x00, 64*1024*1024, 2, 0); acapAddInputBuffer (acapGraph, accelNode2, buffNode1, 0x00, 64*1024*1024, 3, 0); acapAddOutputBuffer(acapGraph, accelNode2, buffNode2, 0x00, 64*1024*1024, 3, 0); acapAddInputBuffer (acapGraph, accelNode3, buffNode2, 0x00, 64*1024*1024, 4, 0); acapAddOutputBuffer(acapGraph, accelNode3, buffNode3, 0x00, 64*1024*1024, 4, 0); acapAddInputBuffer (acapGraph, accelNode4, buffNode3, 0x00, 64*1024*1024, 6, 0); acapGraphConfig(acapGraph); acapGraphToJson(acapGraph); for(int i=0; i < 1024; i++){ p0[i] = i; } printhex((uint32_t*)p0, 0x50); acapGraphSchedule(acapGraph); printhex((uint32_t*)p1, 0x50); acapGraphFinalise(acapGraph); return 0; } int case5(){ INFO("TEST2: \n"); uint8_t *p0 = (uint8_t*) malloc(32*1024*1024); uint8_t *p1 = (uint8_t*) malloc(32*1024*1024); uint8_t *p2 = (uint8_t*) malloc(32*1024*1024); uint8_t *c0 = (uint8_t*) malloc(4*1024); uint8_t *c1 = (uint8_t*) malloc(4*1024); uint8_t *c2 = (uint8_t*) malloc(4*1024); AcapGraph_t *acapGraph = graphInit(); AccelNode_t *config0 = addInputNode(acapGraph, c0, 4*1024, ENABLE_SCHEDULER); AccelNode_t *config1 = addInputNode(acapGraph, c1, 4*1024, ENABLE_SCHEDULER); AccelNode_t *config2 = addInputNode(acapGraph, c2, 4*1024, ENABLE_SCHEDULER); AccelNode_t *accelNode0 = addInputNode(acapGraph, p0, 32*1024*1024, ENABLE_SCHEDULER); AccelNode_t *accelNode1 = addAcceleratorNode(acapGraph, "fir_compiler", ENABLE_SCHEDULER); AccelNode_t *accelNode2 = addAcceleratorNode(acapGraph, "FFT4", ENABLE_SCHEDULER); AccelNode_t *accelNode3 = addAcceleratorNode(acapGraph, "aes128encdec", ENABLE_SCHEDULER); AccelNode_t *accelNode4 = addOutputNode(acapGraph, p1, 32*1024*1024, ENABLE_SCHEDULER); AccelNode_t *accelNode5 = addOutputNode(acapGraph, p2, 32*1024*1024, ENABLE_SCHEDULER); BuffNode_t *buffNode0 = addBuffer(acapGraph, 16*1024*1024, DDR_BASED); BuffNode_t *buffNode1 = addBuffer(acapGraph, 16*1024*1024, DDR_BASED); BuffNode_t *buffNode2 = addBuffer(acapGraph, 16*1024*1024, DDR_BASED); BuffNode_t *buffNode3 = addBuffer(acapGraph, 16*1024*1024, DDR_BASED); BuffNode_t *buffConf0 = addBuffer(acapGraph, 4*1024, DDR_BASED); BuffNode_t *buffConf1 = addBuffer(acapGraph, 4*1024, DDR_BASED); BuffNode_t *buffConf2 = addBuffer(acapGraph, 4*1024, DDR_BASED); addOutBuffer(acapGraph, config0, buffConf0, 0x00, 32, 0, 0); addOutBuffer(acapGraph, config1, buffConf1, 0x00, 32, 1, 0); addOutBuffer(acapGraph, config2, buffConf2, 0x00, 32, 2, 0); addOutBuffer(acapGraph, accelNode0, buffNode0, 0x00, 32*1024*1024, 3, 0); addInBuffer (acapGraph, accelNode1, buffConf0, 0x00, 32, 4, 1); addInBuffer (acapGraph, accelNode2, buffConf1, 0x00, 32, 5, 1); addInBuffer (acapGraph, accelNode3, buffConf2, 0x00, 32, 6, 1); addInBuffer (acapGraph, accelNode1, buffNode0, 0x00, 32*1024*1024, 7, 0); addOutBuffer(acapGraph, accelNode1, buffNode1, 0x00, 32*1024*1024, 7, 0); addInBuffer (acapGraph, accelNode2, buffNode0, 0x00, 32*1024*1024, 8, 0); addOutBuffer(acapGraph, accelNode2, buffNode2, 0x00, 32*1024*1024, 8, 0); addInBuffer (acapGraph, accelNode3, buffNode2, 0x00, 32*1024*1024, 9, 0); addOutBuffer(acapGraph, accelNode3, buffNode3, 0x00, 32*1024*1024, 9, 0); addInBuffer (acapGraph, accelNode4, buffNode1, 0x00, 32*1024*1024, 10, 0); addInBuffer (acapGraph, accelNode5, buffNode3, 0x00, 32*1024*1024, 11, 0); acapGraphConfig(acapGraph); acapGraphToJson(acapGraph); for(int i=0; i < 1024; i++){ p0[i] = i; } printhex((uint32_t*)p0, 0x50); acapGraphSchedule(acapGraph); printhex((uint32_t*)p1, 0x50); printhex((uint32_t*)p2, 0x50); graphFinalise(acapGraph); return 0; } */ int case6(){ INFO("TEST1: CMA buffer with single PL Accelerator\n"); uint8_t *p0 = (uint8_t*) malloc(64*1024*1024); uint8_t *p1 = (uint8_t*) malloc(64*1024*1024); _unused(p0); _unused(p1); AbstractGraph_t *acapGraph = graphInit(); AbstractAccelNode_t *accelNode0 = addInputNode(acapGraph, 64*1024*1024); AbstractAccelNode_t *accelNode3 = addAcceleratorNode(acapGraph, "aes128encdec"); AbstractAccelNode_t *accelNode1 = addAcceleratorNode(acapGraph, "fir_compiler"); AbstractAccelNode_t *accelNode2 = addAcceleratorNode(acapGraph, "FFT4"); //, ENABLE_SCHEDULER); AbstractAccelNode_t *accelNode4 = addOutputNode(acapGraph, 64*1024*1024); AbstractBuffNode_t *buffNode0 = addBuffer(acapGraph, 16*1024*1024, DDR_BASED); AbstractBuffNode_t *buffNode1 = addBuffer(acapGraph, 16*1024*1024, PL_BASED); AbstractBuffNode_t *buffNode2 = addBuffer(acapGraph, 16*1024*1024, PL_BASED); AbstractBuffNode_t *buffNode3 = addBuffer(acapGraph, 16*1024*1024, DDR_BASED); addOutBuffer(acapGraph, accelNode0, buffNode0, 0x00, 64*1024*1024, 1, 0); addInBuffer (acapGraph, accelNode1, buffNode0, 0x00, 64*1024*1024, 2, 0); addOutBuffer(acapGraph, accelNode1, buffNode1, 0x00, 64*1024*1024, 2, 0); addInBuffer (acapGraph, accelNode2, buffNode1, 0x00, 64*1024*1024, 3, 0); addOutBuffer(acapGraph, accelNode2, buffNode2, 0x00, 64*1024*1024, 3, 0); addInBuffer (acapGraph, accelNode3, buffNode2, 0x00, 64*1024*1024, 4, 0); addOutBuffer(acapGraph, accelNode3, buffNode3, 0x00, 64*1024*1024, 4, 0); addInBuffer (acapGraph, accelNode4, buffNode3, 0x00, 64*1024*1024, 6, 0); abstractGraphConfig(acapGraph); for(int i=0; i < 1024; i++){ accelNode0->ptr[i] = i; } sem_post(accelNode0->semptr); sem_wait(accelNode4->semptr); printhex((uint32_t*)accelNode0->ptr, 0x50); printhex((uint32_t*)accelNode4->ptr, 0x50); abstractGraphFinalise(acapGraph); return 0; } /* int case7(){ INFO("TEST2: \n"); uint8_t *p0 = (uint8_t*) malloc(32*1024*1024); uint8_t *p1 = (uint8_t*) malloc(32*1024*1024); uint8_t *p2 = (uint8_t*) malloc(32*1024*1024); uint8_t *c0 = (uint8_t*) malloc(4*1024); uint8_t *c1 = (uint8_t*) malloc(4*1024); uint8_t *c2 = (uint8_t*) malloc(4*1024); uint32_t buff[] = { 0xcca5a729, 0x4b276e90, 0x9a57a7e7, 0xd0bfe1c7, 0xcca5a729, 0x4b276e90, 0x9a57a7e7, 0xd0bfe1c7, 0xcca5a729, 0x4b276e90, 0x9a57a7e7, 0xd0bfe1c7, 0xcca5a729, 0x4b276e90, 0x9a57a7e7, 0xd0bfe1c7, 0xcca5a729, 0x4b276e90, 0x9a57a7e7, 0xd0bfe1c7, 0xcca5a729, 0x4b276e90, 0x9a57a7e7, 0xd0bfe1c7, 0xcca5a729, 0x4b276e90, 0x9a57a7e7, 0xd0bfe1c7, 0xcca5a729, 0x4b276e90, 0x9a57a7e7, 0xd0bfe1c7, 0xcca5a729, 0x4b276e90, 0x9a57a7e7, 0xd0bfe1c7, 0xcca5a729, 0x4b276e90, 0x9a57a7e7, 0xd0bfe1c7, 0xcca5a729, 0x4b276e90, 0x9a57a7e7, 0xd0bfe1c7, 0xcca5a729, 0x4b276e90, 0x9a57a7e7, 0xd0bfe1c7, 0xcca5a729, 0x4b276e90, 0x9a57a7e7, 0xd0bfe1c7, 0xcca5a729, 0x4b276e90, 0x9a57a7e7, 0xd0bfe1c7, 0xcca5a729, 0x4b276e90, 0x9a57a7e7, 0xd0bfe1c7, 0xcca5a729, 0x4b276e90, 0x9a57a7e7, 0xd0bfe1c7, 0xcca5a729, 0x4b276e90, 0x9a57a7e7, 0xd0bfe1c7 }; uint32_t keybuff[] = { 0x0c0d0e0f, 0x08090a0b, 0x04050607, 0x00010203, 0x00000000, 0x00000000, 0x00000000, 0x00000000 }; memcpy(p0, buff, 0x100); memcpy(c0, keybuff, 0x20); AcapGraph_t *acapGraph = graphInit(); AccelNode_t *config0 = addInputNode(acapGraph, c0, 4*1024, ENABLE_SCHEDULER); AccelNode_t *ioNode0 = addInputNode(acapGraph, p0, 32*1024*1024, ENABLE_SCHEDULER); AccelNode_t *accelNode0 = addAcceleratorNode(acapGraph, "fir_compiler", ENABLE_SCHEDULER); AccelNode_t *accelNode1 = addAcceleratorNode(acapGraph, "FFT4", ENABLE_SCHEDULER); AccelNode_t *accelNode2 = addAcceleratorNode(acapGraph, "aes128encdec", ENABLE_SCHEDULER); AccelNode_t *ioNode1 = addOutputNode(acapGraph, p1, 32*1024*1024, ENABLE_SCHEDULER); BuffNode_t *buffNode0 = addBuffer(acapGraph, 16*1024*1024, DDR_BASED); BuffNode_t *buffNode1 = addBuffer(acapGraph, 16*1024*1024, DDR_BASED); BuffNode_t *buffConf0 = addBuffer(acapGraph, 4*1024, DDR_BASED); addOutBuffer(acapGraph, config0, buffConf0, 0x400, 0x20, 0, 0); addOutBuffer(acapGraph, ioNode0, buffNode0, 0x00, 0x100, 1, 0); addInBuffer (acapGraph, accelNode2, buffConf0, 0x400, 0x20, 2, 1); addInBuffer (acapGraph, accelNode2, buffNode0, 0x00, 0x100, 3, 0); addOutBuffer(acapGraph, accelNode2, buffNode1, 0x00, 0x100, 3, 0); addInBuffer (acapGraph, ioNode1, buffNode1, 0x00, 0x100, 4, 0); printhex((uint32_t*)p0, 0x100); acapGraphConfig(acapGraph); acapGraphToJson(acapGraph); printhex((uint32_t*)p0, 0x100); acapGraphSchedule(acapGraph); printhex((uint32_t*)p1, 0x100); graphFinalise(acapGraph); return 0; } int case8(){ int i =0; INFO("TEST: FFT only \n"); uint8_t *p0 = (uint8_t*) malloc(32*1024*1024); uint8_t *p1 = (uint8_t*) malloc(32*1024*1024); //uint8_t *p2 = (uint8_t*) malloc(32*1024*1024); uint8_t *c0 = (uint8_t*) malloc(4*1024); uint32_t config[] = {0x0000000c,0x0000000c,0x0000000c,0x0000000c}; uint32_t fftbuff[] = { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000}; for (i=0;i<(0x1000000/0x100);i++){ memcpy(p0 + (i*0x100), fftbuff, 0x100); } memcpy(c0, config, 0x10); AcapGraph_t *acapGraph = graphInit(); AccelNode_t *config0 = addInputNode(acapGraph, c0, 4*1024, ENABLE_SCHEDULER); AccelNode_t *ioNode0 = addInputNode(acapGraph, p0, 32*1024*1024, ENABLE_SCHEDULER); AccelNode_t *accelNode0 = addAcceleratorNode(acapGraph, "fir_compiler", ENABLE_SCHEDULER); AccelNode_t *accelNode1 = addAcceleratorNode(acapGraph, "FFT4", ENABLE_SCHEDULER); AccelNode_t *accelNode2 = addAcceleratorNode(acapGraph, "aes128encdec", ENABLE_SCHEDULER); AccelNode_t *ioNode1 = addOutputNode(acapGraph, p1, 32*1024*1024, ENABLE_SCHEDULER); BuffNode_t *buffNode0 = addBuffer(acapGraph, 16*1024*1024, DDR_BASED); BuffNode_t *buffNode1 = addBuffer(acapGraph, 16*1024*1024, DDR_BASED); BuffNode_t *buffConf0 = addBuffer(acapGraph, 4*1024, DDR_BASED); BuffNode_t *buffConf1 = addBuffer(acapGraph, 4*1024, DDR_BASED); BuffNode_t *buffConf2 = addBuffer(acapGraph, 4*1024, DDR_BASED); BuffNode_t *buffConf3 = addBuffer(acapGraph, 4*1024, DDR_BASED); addOutBuffer(acapGraph, config0, buffConf0, 0x000, 0x10, 0, 0); addOutBuffer(acapGraph, config0, buffConf1, 0x400, 0x10, 1, 0); addOutBuffer(acapGraph, config0, buffConf2, 0x800, 0x10, 2, 0); addOutBuffer(acapGraph, config0, buffConf3, 0xc00, 0x10, 3, 0); addOutBuffer(acapGraph, ioNode0, buffNode0, 0x00, 0x1000000, 4, 0); addInBuffer (acapGraph, accelNode1, buffConf0, 0x00, 0x10, 5, 1); addInBuffer (acapGraph, accelNode1, buffConf1, 0x400, 0x10, 6, 2); addInBuffer (acapGraph, accelNode1, buffConf2, 0x800, 0x10, 7, 3); addInBuffer (acapGraph, accelNode1, buffConf3, 0xc00, 0x10, 8, 4); addInBuffer (acapGraph, accelNode1, buffNode0, 0x00, 0x1000000, 9, 0); addOutBuffer(acapGraph, accelNode1, buffNode1, 0x00, 0x1000000, 9, 0); addInBuffer (acapGraph, ioNode1, buffNode1, 0x00, 0x1000000, 10, 0); acapGraphConfig(acapGraph); acapGraphToJson(acapGraph); printhex((uint32_t*)p0, 0x100); acapGraphSchedule(acapGraph); printhex((uint32_t*)p1, 0x100); graphFinalise(acapGraph); return 0; } int case9(){ INFO("TEST2: \n"); uint8_t *p0 = (uint8_t*) malloc(32*1024*1024); uint8_t *p1 = (uint8_t*) malloc(32*1024*1024); uint8_t *p2 = (uint8_t*) malloc(32*1024*1024); uint8_t *c0 = (uint8_t*) malloc(4*1024); uint8_t *c1 = (uint8_t*) malloc(4*1024); uint8_t *c2 = (uint8_t*) malloc(4*1024); uint32_t buff[] = { 0xcca5a729, 0x4b276e90, 0x9a57a7e7, 0xd0bfe1c7, 0xcca5a729, 0x4b276e90, 0x9a57a7e7, 0xd0bfe1c7, 0xcca5a729, 0x4b276e90, 0x9a57a7e7, 0xd0bfe1c7, 0xcca5a729, 0x4b276e90, 0x9a57a7e7, 0xd0bfe1c7, 0xcca5a729, 0x4b276e90, 0x9a57a7e7, 0xd0bfe1c7, 0xcca5a729, 0x4b276e90, 0x9a57a7e7, 0xd0bfe1c7, 0xcca5a729, 0x4b276e90, 0x9a57a7e7, 0xd0bfe1c7, 0xcca5a729, 0x4b276e90, 0x9a57a7e7, 0xd0bfe1c7, 0xcca5a729, 0x4b276e90, 0x9a57a7e7, 0xd0bfe1c7, 0xcca5a729, 0x4b276e90, 0x9a57a7e7, 0xd0bfe1c7, 0xcca5a729, 0x4b276e90, 0x9a57a7e7, 0xd0bfe1c7, 0xcca5a729, 0x4b276e90, 0x9a57a7e7, 0xd0bfe1c7, 0xcca5a729, 0x4b276e90, 0x9a57a7e7, 0xd0bfe1c7, 0xcca5a729, 0x4b276e90, 0x9a57a7e7, 0xd0bfe1c7, 0xcca5a729, 0x4b276e90, 0x9a57a7e7, 0xd0bfe1c7, 0xcca5a729, 0x4b276e90, 0x9a57a7e7, 0xd0bfe1c7, 0xcca5a729, 0x4b276e90, 0x9a57a7e7, 0xd0bfe1c7 }; uint32_t keybuff[] = { 0x0c0d0e0f, 0x08090a0b, 0x04050607, 0x00010203, 0x00000000, 0x00000000, 0x00000000, 0x00000000 }; memcpy(p0, buff, 0x100); memcpy(c0, keybuff, 0x20); AcapGraph_t *acapGraph = graphInit(); AccelNode_t *config0 = addInputNode(acapGraph, c0, 4*1024, DISABLE_SCHEDULER); AccelNode_t *ioNode0 = addInputNode(acapGraph, p0, 32*1024*1024, DISABLE_SCHEDULER); AccelNode_t *accelNode0 = addAcceleratorNode(acapGraph, "fir_compiler", DISABLE_SCHEDULER); AccelNode_t *accelNode1 = addAcceleratorNode(acapGraph, "FFT4", DISABLE_SCHEDULER); AccelNode_t *accelNode2 = addAcceleratorNode(acapGraph, "aes128encdec", DISABLE_SCHEDULER); AccelNode_t *ioNode1 = addOutputNode(acapGraph, p1, 32*1024*1024, DISABLE_SCHEDULER); BuffNode_t *buffNode0 = addBuffer(acapGraph, 16*1024*1024, DDR_BASED); BuffNode_t *buffNode1 = addBuffer(acapGraph, 16*1024*1024, DDR_BASED); BuffNode_t *buffConf0 = addBuffer(acapGraph, 4*1024, DDR_BASED); addOutBuffer(acapGraph, config0, buffConf0, 0x400, 0x20, 0, 0); addOutBuffer(acapGraph, ioNode0, buffNode0, 0x00, 0x100, 1, 0); addInBuffer (acapGraph, accelNode2, buffConf0, 0x400, 0x20, 2, 1); addInBuffer (acapGraph, accelNode2, buffNode0, 0x00, 0x100, 3, 0); addOutBuffer(acapGraph, accelNode2, buffNode1, 0x00, 0x100, 3, 0); addInBuffer (acapGraph, ioNode1, buffNode1, 0x00, 0x100, 4, 0); acapGraphConfig(acapGraph); acapGraphToJson(acapGraph); acapGraphSchedule(acapGraph); printhex((uint32_t*)p0, 0x100); printhex((uint32_t*)p1, 0x100); *//*acapGraphResetLinks(acapGraph); graphFinalise(acapGraph); addOutBuffer(acapGraph, config0, buffConf0, 0x400, 0x20, 0, 0); addOutBuffer(acapGraph, ioNode0, buffNode0, 0x00, 0x100, 1, 0); addInBuffer (acapGraph, accelNode2, buffConf0, 0x400, 0x20, 2, 1); addInBuffer (acapGraph, accelNode2, buffNode0, 0x00, 0x100, 3, 0); addOutBuffer(acapGraph, accelNode2, buffNode1, 0x00, 0x100, 3, 0); addInBuffer (acapGraph, ioNode1, buffNode1, 0x00, 0x100, 4, 0); acapGraphConfig(acapGraph); acapGraphToJson(acapGraph); acapGraphSchedule(acapGraph); printhex((uint32_t*)p0, 0x100); printhex((uint32_t*)p1, 0x100);*//* return 0; }*/ int main(void){ /*int drm_fd; int size = 0x1000000; int handle = -1; uint8_t* ptr = NULL; unsigned long paddr; int fd; int status; drm_fd = open("/dev/dri/renderD128", O_RDWR); if (drm_fd < 0) { return -1; } status = xrt_allocateBuffer(drm_fd, size, &handle, &ptr, &paddr, &fd); printf("%d\n", status); sleep(10); close(fd); status = xrt_deallocateBuffer(drm_fd, size, &handle, &ptr); printf("%d\n", status); close(drm_fd); */ //case0(); case1(); //case2(); //case3(); //case4(); //case5(); //case6(); //case7(); //case8(); //case9(); return 0; } dfx-mgr-xilinx_v2023.2/example/sys/linux/graph/graphTest0.c000066400000000000000000000015711446677152000236450ustar00rootroot00000000000000/* * Copyright (c) 2021, Xilinx Inc. and Contributors. All rights reserved. * * SPDX-License-Identifier: MIT */ #include #include #include #include #include #include #include #include #include #include #include int main(void){ INFO("TEST0: Just load CMA buffer without PL Accelerator"); AbstractGraph_t *acapGraph = graphInit(); AbstractAccelNode_t *accelNode0 = addInputNode(acapGraph, 32*1024*1024); AbstractAccelNode_t *accelNode1 = addOutputNode(acapGraph, 32*1024*1024); _unused(accelNode0); _unused(accelNode1); abstractGraphConfig(acapGraph); for(int i=0; i < 1024; i++){ accelNode0->ptr[i] = i; } abstractGraphFinalise(acapGraph); return 0; } dfx-mgr-xilinx_v2023.2/example/sys/linux/graph/graphTest1.c000066400000000000000000000025211446677152000236420ustar00rootroot00000000000000/* * Copyright (c) 2021, Xilinx Inc. and Contributors. All rights reserved. * * SPDX-License-Identifier: MIT */ #include #include #include #include #include #include #include #include #include #include #include int main(void){ int status; INFO("TEST1: Load CMA buffer without PL Accelerator and test transactions\n"); AbstractGraph_t *acapGraph = graphInit(); AbstractAccelNode_t *accelNode0 = addInputNode(acapGraph, 32*1024*1024); AbstractAccelNode_t *accelNode1 = addOutputNode(acapGraph, 32*1024*1024); AbstractBuffNode_t *buffNode0 = addBuffer(acapGraph, 16*1024*1024, DDR_BASED); addOutBuffer(acapGraph, accelNode0, buffNode0, 0x00, 32*1024*1024, 1, 0); addInBuffer (acapGraph, accelNode1, buffNode0, 0x00, 32*1024*1024, 2, 0); status = abstractGraphConfig(acapGraph); if(status < 0){ printf("Seems like GraphDaemon not running ...!!\n"); return -1; } for(int i=0; i < 1024; i++){ accelNode0->ptr[i] = i; } sem_post(accelNode0->semptr); sem_wait(accelNode1->semptr); printhex((uint32_t*)accelNode0->ptr, 0x50); printhex((uint32_t*)accelNode1->ptr, 0x50); abstractGraphFinalise(acapGraph); return 0; } dfx-mgr-xilinx_v2023.2/example/sys/linux/graph/graphTest2.c000066400000000000000000000031711446677152000236450ustar00rootroot00000000000000/* * Copyright (c) 2021, Xilinx Inc. and Contributors. All rights reserved. * * SPDX-License-Identifier: MIT */ #include #include #include #include #include #include #include #include #include #include #include int main(void){ int status; INFO("######### TEST2: CMA buffer with single PL Accelerator\n"); AbstractGraph_t *acapGraph = graphInit(); AbstractAccelNode_t *accelNode0 = addInputNode(acapGraph, 32*1024*1024); AbstractAccelNode_t *accelNode1 = addAcceleratorNode(acapGraph, "AES192"); AbstractAccelNode_t *accelNode2 = addOutputNode(acapGraph, 32*1024*1024); AbstractBuffNode_t *buffNode0 = addBuffer(acapGraph, 16*1024*1024, DDR_BASED); AbstractBuffNode_t *buffNode1 = addBuffer(acapGraph, 16*1024*1024, DDR_BASED); addOutBuffer(acapGraph, accelNode0, buffNode0, 0x00, 32*1024*1024, 1, 0); addInBuffer (acapGraph, accelNode1, buffNode0, 0x00, 32*1024*1024, 2, 0); addOutBuffer(acapGraph, accelNode1, buffNode1, 0x00, 32*1024*1024, 2, 0); addInBuffer (acapGraph, accelNode2, buffNode1, 0x00, 32*1024*1024, 3, 0); status = abstractGraphConfig(acapGraph); if(status < 0){ printf("Seems like GraphDaemon not running ...!!\n"); return -1; } for(int i=0; i < 1024; i++){ accelNode0->ptr[i] = i; } sem_post(accelNode0->semptr); sem_wait(accelNode2->semptr); printhex((uint32_t*)accelNode0->ptr, 0x50); printhex((uint32_t*)accelNode2->ptr, 0x50); abstractGraphFinalise(acapGraph); return 0; } dfx-mgr-xilinx_v2023.2/example/sys/linux/graph/graphTest3.c000066400000000000000000000043101446677152000236420ustar00rootroot00000000000000/* * Copyright (c) 2021, Xilinx Inc. and Contributors. All rights reserved. * * SPDX-License-Identifier: MIT */ #include #include #include #include #include #include #include #include #include #include #include int main(void){ int status; INFO("TEST3: Test Accel Chain\n"); AbstractGraph_t *acapGraph = graphInit(); AbstractAccelNode_t *accelNode0 = addInputNode(acapGraph, 32*1024*1024); AbstractAccelNode_t *accelNode1 = addAcceleratorNode(acapGraph, "AES128"); AbstractAccelNode_t *accelNode2 = addAcceleratorNode(acapGraph, "AES128"); //AbstractAccelNode_t *accelNode3 = addAcceleratorNode(acapGraph, "AES128"); AbstractAccelNode_t *accelNode4 = addOutputNode(acapGraph, 32*1024*1024); AbstractBuffNode_t *buffNode0 = addBuffer(acapGraph, 16*1024*1024, DDR_BASED); AbstractBuffNode_t *buffNode1 = addBuffer(acapGraph, 16*1024*1024, DDR_BASED); AbstractBuffNode_t *buffNode2 = addBuffer(acapGraph, 16*1024*1024, DDR_BASED); //AbstractBuffNode_t *buffNode3 = addBuffer(acapGraph, 16*1024*1024, DDR_BASED); addOutBuffer(acapGraph, accelNode0, buffNode0, 0x00, 32*1024*1024, 1, 0); addInBuffer (acapGraph, accelNode1, buffNode0, 0x00, 32*1024*1024, 2, 0); addOutBuffer(acapGraph, accelNode1, buffNode1, 0x00, 32*1024*1024, 2, 0); addInBuffer (acapGraph, accelNode2, buffNode1, 0x00, 32*1024*1024, 3, 0); addOutBuffer(acapGraph, accelNode2, buffNode2, 0x00, 32*1024*1024, 3, 0); //addInBuffer (acapGraph, accelNode3, buffNode2, 0x00, 32*1024*1024, 4, 0); //addOutBuffer(acapGraph, accelNode3, buffNode3, 0x00, 32*1024*1024, 4, 0); addInBuffer (acapGraph, accelNode4, buffNode2, 0x00, 32*1024*1024, 6, 0); status = abstractGraphConfig(acapGraph); if(status < 0){ printf("Seems like GraphDaemon not running ...!!\n"); return -1; } for(int i=0; i < 1024; i++){ accelNode0->ptr[i] = i; } sem_post(accelNode0->semptr); sem_wait(accelNode4->semptr); printhex((uint32_t*)accelNode0->ptr, 0x50); printhex((uint32_t*)accelNode4->ptr, 0x50); abstractGraphFinalise(acapGraph); return 0; } dfx-mgr-xilinx_v2023.2/example/sys/linux/graph/graphTest4.c000066400000000000000000000043721446677152000236530ustar00rootroot00000000000000/* * Copyright (c) 2021, Xilinx Inc. and Contributors. All rights reserved. * * SPDX-License-Identifier: MIT */ #include #include #include #include #include #include #include #include #include #include #include int main(void){ int status; INFO("TEST4: Test Accel Chain with interRM\n"); AbstractGraph_t *acapGraph = graphInit(); AbstractAccelNode_t *accelNode0 = addInputNode(acapGraph, 32*1024*1024); AbstractAccelNode_t *accelNode1 = addAcceleratorNode(acapGraph, "fir_compiler"); AbstractAccelNode_t *accelNode2 = addAcceleratorNode(acapGraph, "FFT4"); AbstractAccelNode_t *accelNode3 = addAcceleratorNode(acapGraph, "aes128encdec"); AbstractAccelNode_t *accelNode4 = addOutputNode(acapGraph, 32*1024*1024); AbstractBuffNode_t *buffNode0 = addBuffer(acapGraph, 16*1024*1024, DDR_BASED); AbstractBuffNode_t *buffNode1 = addBuffer(acapGraph, 16*1024*1024, PL_BASED); AbstractBuffNode_t *buffNode2 = addBuffer(acapGraph, 16*1024*1024, PL_BASED); AbstractBuffNode_t *buffNode3 = addBuffer(acapGraph, 16*1024*1024, DDR_BASED); addOutBuffer(acapGraph, accelNode0, buffNode0, 0x00, 32*1024*1024, 1, 0); addInBuffer (acapGraph, accelNode1, buffNode0, 0x00, 32*1024*1024, 2, 0); addOutBuffer(acapGraph, accelNode1, buffNode1, 0x00, 32*1024*1024, 2, 0); addInBuffer (acapGraph, accelNode2, buffNode1, 0x00, 32*1024*1024, 3, 0); addOutBuffer(acapGraph, accelNode2, buffNode2, 0x00, 32*1024*1024, 3, 0); addInBuffer (acapGraph, accelNode3, buffNode2, 0x00, 32*1024*1024, 4, 0); addOutBuffer(acapGraph, accelNode3, buffNode3, 0x00, 32*1024*1024, 4, 0); addInBuffer (acapGraph, accelNode4, buffNode3, 0x00, 32*1024*1024, 5, 0); status = abstractGraphConfig(acapGraph); if(status < 0){ printf("Seems like GraphDaemon not running ...!!\n"); return -1; } for(int i=0; i < 1024; i++){ accelNode0->ptr[i] = i; } sem_post(accelNode0->semptr); printf("###\n"); sem_wait(accelNode4->semptr); printf("###\n"); printhex((uint32_t*)accelNode0->ptr, 0x50); printhex((uint32_t*)accelNode4->ptr, 0x50); abstractGraphFinalise(acapGraph); return 0; } dfx-mgr-xilinx_v2023.2/example/sys/linux/graph/graphTest5.c000066400000000000000000000043741446677152000236560ustar00rootroot00000000000000/* * Copyright (c) 2021, Xilinx Inc. and Contributors. All rights reserved. * * SPDX-License-Identifier: MIT */ #include #include #include #include #include #include #include #include #include #include #include int main(void){ int status; INFO("TEST4: Test Accel Chain with interRM\n"); AbstractGraph_t *acapGraph = graphInit(); AbstractAccelNode_t *accelNode0 = addInputNode(acapGraph, 32*1024*1024); AbstractAccelNode_t *accelNode1 = addAcceleratorNode(acapGraph, "fir_compiler"); AbstractAccelNode_t *accelNode2 = addAcceleratorNode(acapGraph, "FFT4"); AbstractAccelNode_t *accelNode3 = addAcceleratorNode(acapGraph, "aes128encdec"); AbstractAccelNode_t *accelNode4 = addOutputNode(acapGraph, 32*1024*1024); AbstractBuffNode_t *buffNode0 = addBuffer(acapGraph, 16*1024*1024, DDR_BASED); AbstractBuffNode_t *buffNode1 = addBuffer(acapGraph, 16*1024*1024, DDR_BASED); AbstractBuffNode_t *buffNode2 = addBuffer(acapGraph, 16*1024*1024, DDR_BASED); AbstractBuffNode_t *buffNode3 = addBuffer(acapGraph, 16*1024*1024, DDR_BASED); addOutBuffer(acapGraph, accelNode0, buffNode0, 0x00, 32*1024*1024, 1, 0); addInBuffer (acapGraph, accelNode1, buffNode0, 0x00, 32*1024*1024, 2, 0); addOutBuffer(acapGraph, accelNode1, buffNode1, 0x00, 32*1024*1024, 2, 0); addInBuffer (acapGraph, accelNode2, buffNode1, 0x00, 32*1024*1024, 3, 0); addOutBuffer(acapGraph, accelNode2, buffNode2, 0x00, 32*1024*1024, 3, 0); addInBuffer (acapGraph, accelNode3, buffNode2, 0x00, 32*1024*1024, 4, 0); addOutBuffer(acapGraph, accelNode3, buffNode3, 0x00, 32*1024*1024, 4, 0); addInBuffer (acapGraph, accelNode4, buffNode3, 0x00, 32*1024*1024, 5, 0); status = abstractGraphConfig(acapGraph); if(status < 0){ printf("Seems like GraphDaemon not running ...!!\n"); return -1; } for(int i=0; i < 1024; i++){ accelNode0->ptr[i] = i; } sem_post(accelNode0->semptr); printf("###\n"); sem_wait(accelNode4->semptr); printf("###\n"); printhex((uint32_t*)accelNode0->ptr, 0x50); printhex((uint32_t*)accelNode4->ptr, 0x50); abstractGraphFinalise(acapGraph); return 0; } dfx-mgr-xilinx_v2023.2/example/sys/linux/load_accel.c000066400000000000000000000013051446677152000225640ustar00rootroot00000000000000#include #include #include #include #include #include #include #include #include static char uio_path[NAME_MAX]; int main(int argc, char *argv[]) { int ret; if (argc < 2) { printf("Enter the package to load\n"); return 0; } ret = dfxmgr_load(argv[1]); printf("dfxmgr_load returned %d\n", ret); dfxmgr_uio_by_name(uio_path, ret, "SIHA"); printf("%s SIHA\n", uio_path); dfxmgr_uio_by_name(uio_path, ret, "AccelConfig"); printf("%s AccelConfig\n", uio_path); dfxmgr_uio_by_name(uio_path, ret, "rm_comm_box"); printf("%s rm_comm_box\n", uio_path); return dfxmgr_remove(ret); } dfx-mgr-xilinx_v2023.2/include/000077500000000000000000000000001446677152000163665ustar00rootroot00000000000000dfx-mgr-xilinx_v2023.2/include/jsmn.h000066400000000000000000000275051446677152000175170ustar00rootroot00000000000000/* * MIT License * * Copyright (c) 2010 Serge Zaitsev * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE * SOFTWARE. */ #ifndef JSMN_H #define JSMN_H #include #ifdef __cplusplus extern "C" { #endif #ifdef JSMN_STATIC #define JSMN_API static #else #define JSMN_API extern #endif /** * JSON type identifier. Basic types are: * o Object * o Array * o String * o Other primitive: number, boolean (true/false) or null */ typedef enum { JSMN_UNDEFINED = 0, JSMN_OBJECT = 1, JSMN_ARRAY = 2, JSMN_STRING = 3, JSMN_PRIMITIVE = 4 } jsmntype_t; enum jsmnerr { /* Not enough tokens were provided */ JSMN_ERROR_NOMEM = -1, /* Invalid character inside JSON string */ JSMN_ERROR_INVAL = -2, /* The string is not a full JSON packet, more bytes expected */ JSMN_ERROR_PART = -3 }; /** * JSON token description. * type type (object, array, string etc.) * start start position in JSON data string * end end position in JSON data string */ typedef struct { jsmntype_t type; int start; int end; int size; #ifdef JSMN_PARENT_LINKS int parent; #endif } jsmntok_t; /** * JSON parser. Contains an array of token blocks available. Also stores * the string being parsed now and current position in that string. */ typedef struct { unsigned int pos; /* offset in the JSON string */ unsigned int toknext; /* next token to allocate */ int toksuper; /* superior token node, e.g. parent object or array */ } jsmn_parser; /** * Create JSON parser over an array of tokens */ JSMN_API void jsmn_init(jsmn_parser *parser); /** * Run JSON parser. It parses a JSON data string into and array of tokens, each * describing * a single JSON object. */ JSMN_API int jsmn_parse(jsmn_parser *parser, const char *js, const size_t len, jsmntok_t *tokens, const unsigned int num_tokens); #ifndef JSMN_HEADER /** * Allocates a fresh unused token from the token pool. */ static jsmntok_t *jsmn_alloc_token(jsmn_parser *parser, jsmntok_t *tokens, const size_t num_tokens) { jsmntok_t *tok; if (parser->toknext >= num_tokens) { return NULL; } tok = &tokens[parser->toknext++]; tok->start = tok->end = -1; tok->size = 0; #ifdef JSMN_PARENT_LINKS tok->parent = -1; #endif return tok; } /** * Fills token type and boundaries. */ static void jsmn_fill_token(jsmntok_t *token, const jsmntype_t type, const int start, const int end) { token->type = type; token->start = start; token->end = end; token->size = 0; } /** * Fills next available token with JSON primitive. */ static int jsmn_parse_primitive(jsmn_parser *parser, const char *js, const size_t len, jsmntok_t *tokens, const size_t num_tokens) { jsmntok_t *token; int start; start = parser->pos; for (; parser->pos < len && js[parser->pos] != '\0'; parser->pos++) { switch (js[parser->pos]) { #ifndef JSMN_STRICT /* In strict mode primitive must be followed by "," or "}" or "]" */ case ':': #endif case '\t': case '\r': case '\n': case ' ': case ',': case ']': case '}': goto found; default: /* to quiet a warning from gcc*/ break; } if (js[parser->pos] < 32 || js[parser->pos] >= 127) { parser->pos = start; return JSMN_ERROR_INVAL; } } #ifdef JSMN_STRICT /* In strict mode primitive must be followed by a comma/object/array */ parser->pos = start; return JSMN_ERROR_PART; #endif found: if (tokens == NULL) { parser->pos--; return 0; } token = jsmn_alloc_token(parser, tokens, num_tokens); if (token == NULL) { parser->pos = start; return JSMN_ERROR_NOMEM; } jsmn_fill_token(token, JSMN_PRIMITIVE, start, parser->pos); #ifdef JSMN_PARENT_LINKS token->parent = parser->toksuper; #endif parser->pos--; return 0; } /** * Fills next token with JSON string. */ static int jsmn_parse_string(jsmn_parser *parser, const char *js, const size_t len, jsmntok_t *tokens, const size_t num_tokens) { jsmntok_t *token; int start = parser->pos; parser->pos++; /* Skip starting quote */ for (; parser->pos < len && js[parser->pos] != '\0'; parser->pos++) { char c = js[parser->pos]; /* Quote: end of string */ if (c == '\"') { if (tokens == NULL) { return 0; } token = jsmn_alloc_token(parser, tokens, num_tokens); if (token == NULL) { parser->pos = start; return JSMN_ERROR_NOMEM; } jsmn_fill_token(token, JSMN_STRING, start + 1, parser->pos); #ifdef JSMN_PARENT_LINKS token->parent = parser->toksuper; #endif return 0; } /* Backslash: Quoted symbol expected */ if (c == '\\' && parser->pos + 1 < len) { int i; parser->pos++; switch (js[parser->pos]) { /* Allowed escaped symbols */ case '\"': case '/': case '\\': case 'b': case 'f': case 'r': case 'n': case 't': break; /* Allows escaped symbol \uXXXX */ case 'u': parser->pos++; for (i = 0; i < 4 && parser->pos < len && js[parser->pos] != '\0'; i++) { /* If it isn't a hex character we have an error */ if (!((js[parser->pos] >= 48 && js[parser->pos] <= 57) || /* 0-9 */ (js[parser->pos] >= 65 && js[parser->pos] <= 70) || /* A-F */ (js[parser->pos] >= 97 && js[parser->pos] <= 102))) { /* a-f */ parser->pos = start; return JSMN_ERROR_INVAL; } parser->pos++; } parser->pos--; break; /* Unexpected symbol */ default: parser->pos = start; return JSMN_ERROR_INVAL; } } } parser->pos = start; return JSMN_ERROR_PART; } /** * Parse JSON string and fill tokens. */ JSMN_API int jsmn_parse(jsmn_parser *parser, const char *js, const size_t len, jsmntok_t *tokens, const unsigned int num_tokens) { int r; int i; jsmntok_t *token; int count = parser->toknext; for (; parser->pos < len && js[parser->pos] != '\0'; parser->pos++) { char c; jsmntype_t type; c = js[parser->pos]; switch (c) { case '{': case '[': count++; if (tokens == NULL) { break; } token = jsmn_alloc_token(parser, tokens, num_tokens); if (token == NULL) { return JSMN_ERROR_NOMEM; } if (parser->toksuper != -1) { jsmntok_t *t = &tokens[parser->toksuper]; #ifdef JSMN_STRICT /* In strict mode an object or array can't become a key */ if (t->type == JSMN_OBJECT) { return JSMN_ERROR_INVAL; } #endif t->size++; #ifdef JSMN_PARENT_LINKS token->parent = parser->toksuper; #endif } token->type = (c == '{' ? JSMN_OBJECT : JSMN_ARRAY); token->start = parser->pos; parser->toksuper = parser->toknext - 1; break; case '}': case ']': if (tokens == NULL) { break; } type = (c == '}' ? JSMN_OBJECT : JSMN_ARRAY); #ifdef JSMN_PARENT_LINKS if (parser->toknext < 1) { return JSMN_ERROR_INVAL; } token = &tokens[parser->toknext - 1]; for (;;) { if (token->start != -1 && token->end == -1) { if (token->type != type) { return JSMN_ERROR_INVAL; } token->end = parser->pos + 1; parser->toksuper = token->parent; break; } if (token->parent == -1) { if (token->type != type || parser->toksuper == -1) { return JSMN_ERROR_INVAL; } break; } token = &tokens[token->parent]; } #else for (i = parser->toknext - 1; i >= 0; i--) { token = &tokens[i]; if (token->start != -1 && token->end == -1) { if (token->type != type) { return JSMN_ERROR_INVAL; } parser->toksuper = -1; token->end = parser->pos + 1; break; } } /* Error if unmatched closing bracket */ if (i == -1) { return JSMN_ERROR_INVAL; } for (; i >= 0; i--) { token = &tokens[i]; if (token->start != -1 && token->end == -1) { parser->toksuper = i; break; } } #endif break; case '\"': r = jsmn_parse_string(parser, js, len, tokens, num_tokens); if (r < 0) { return r; } count++; if (parser->toksuper != -1 && tokens != NULL) { tokens[parser->toksuper].size++; } break; case '\t': case '\r': case '\n': case ' ': break; case ':': parser->toksuper = parser->toknext - 1; break; case ',': if (tokens != NULL && parser->toksuper != -1 && tokens[parser->toksuper].type != JSMN_ARRAY && tokens[parser->toksuper].type != JSMN_OBJECT) { #ifdef JSMN_PARENT_LINKS parser->toksuper = tokens[parser->toksuper].parent; #else for (i = parser->toknext - 1; i >= 0; i--) { if (tokens[i].type == JSMN_ARRAY || tokens[i].type == JSMN_OBJECT) { if (tokens[i].start != -1 && tokens[i].end == -1) { parser->toksuper = i; break; } } } #endif } break; #ifdef JSMN_STRICT /* In strict mode primitives are: numbers and booleans */ case '-': case '0': case '1': case '2': case '3': case '4': case '5': case '6': case '7': case '8': case '9': case 't': case 'f': case 'n': /* And they must not be keys of the object */ if (tokens != NULL && parser->toksuper != -1) { const jsmntok_t *t = &tokens[parser->toksuper]; if (t->type == JSMN_OBJECT || (t->type == JSMN_STRING && t->size != 0)) { return JSMN_ERROR_INVAL; } } #else /* In non-strict mode every unquoted value is a primitive */ default: #endif r = jsmn_parse_primitive(parser, js, len, tokens, num_tokens); if (r < 0) { return r; } count++; if (parser->toksuper != -1 && tokens != NULL) { tokens[parser->toksuper].size++; } break; #ifdef JSMN_STRICT /* Unexpected char in strict mode */ default: return JSMN_ERROR_INVAL; #endif } } if (tokens != NULL) { for (i = parser->toknext - 1; i >= 0; i--) { /* Unmatched opened object or array */ if (tokens[i].start != -1 && tokens[i].end == -1) { return JSMN_ERROR_PART; } } } return count; } /** * Creates a new parser based over a given buffer with an array of tokens * available. */ JSMN_API void jsmn_init(jsmn_parser *parser) { parser->pos = 0; parser->toknext = 0; parser->toksuper = -1; } #endif /* JSMN_HEADER */ #ifdef __cplusplus } #endif #endif /* JSMN_H */ dfx-mgr-xilinx_v2023.2/include/zynq_ioctl.h000066400000000000000000000407221446677152000207370ustar00rootroot00000000000000/* SPDX-License-Identifier: GPL-2.0 OR Apache-2.0 */ /* * A GEM style CMA backed memory manager for ZynQ based OpenCL accelerators. * * Copyright (C) 2016-2020 Xilinx, Inc. All rights reserved. * * Authors: * Sonal Santan * Umang Parekh * Min Ma * * This file is dual-licensed; you may select either the GNU General Public * License version 2 or Apache License, Version 2.0. */ /** * DOC: A GEM style driver for Xilinx edge based accelerators * This file defines ioctl command codes and associated structures for interacting with * *zocl* driver for Xilinx FPGA platforms(Zynq/ZynqMP/Versal). * * Accelerator memory allocation is modeled as buffer objects (bo). zocl * supports both SMMU based shared virtual memory and CMA based shared physical memory * between PS and PL. zocl also supports memory management of PL-DDRs and PL-BRAMs. * PL-DDR is reserved by zocl driver via device tree. Both PS Linux and PL logic can access PL-DDRs * * Execution model is asynchronous where execute commands are submitted using command buffers and * POSIX poll is used to wait for finished commands. Commands for a compute unit can only be submitted * after an explicit context has been opened by the client for that compute unit. * * *zocl* driver functionality is described in the following table. * * ==== ====================================== ============================== ================================== * # Functionality ioctl request code data format * ==== ====================================== ============================== ================================== * 1 Allocate buffer on device DRM_IOCTL_ZOCL_CREATE_BO drm_zocl_create_bo * 2 Allocate buffer on device with DRM_IOCTL_ZOCL_USERPTR_BO drm_zocl_userptr_bo * userptr * 3 Get the buffer handle of given DRM_IOCTL_ZOCL_GET_HOST_BO drm_zocl_host_bo * physical address * 4 Prepare bo for mapping into user's DRM_IOCTL_ZOCL_MAP_BO drm_zocl_map_bo * address space * 5 Synchronize (DMA) buffer contents in DRM_IOCTL_ZOCL_SYNC_BO drm_zocl_sync_bo * requested direction * 6 Obtain information about buffer DRM_IOCTL_ZOCL_INFO_BO drm_zocl_info_bo * object * 7 Update bo backing storage with user's DRM_IOCTL_ZOCL_PWRITE_BO drm_zocl_pwrite_bo * data * 8 Read back data in bo backing storage DRM_IOCTL_ZOCL_PREAD_BO drm_zocl_pread_bo * 9 Update device view with a specific DRM_IOCTL_ZOCL_PCAP_DOWNLOAD drm_zocl_pcap_download * xclbin image * 10 Read the xclbin and map the compute DRM_IOCTL_ZOCL_READ_AXLF drm_zocl_axlf * units. * 11 Send an execute job to a compute unit DRM_IOCTL_ZOCL_EXECBUF drm_zocl_execbuf * 12 Get the soft kernel command DRM_IOCTL_ZOCL_SK_GETCMD drm_zocl_sk_getcmd * (experimental) * 13 Create the soft kernel DRM_IOCTL_ZOCL_SK_CREATE drm_zocl_sk_create * (experimental) * 14 Report the soft kernel state DRM_IOCTL_ZOCL_SK_REPORT drm_zocl_sk_report * (experimental) * 15 Get Information about Compute Unit DRM_IOCTL_ZOCL_INFO_CU drm_zocl_info_cu * (experimental) * * ==== ====================================== ============================== ================================== */ #ifndef __ZYNQ_IOCTL_H__ #define __ZYNQ_IOCTL_H__ #ifndef __KERNEL__ #include #include #include #else #include #endif /* !__KERNEL__ */ /* * enum drm_zocl_ops - ioctl command code enumerations */ enum drm_zocl_ops { /* Buffer creation */ DRM_ZOCL_CREATE_BO = 0, /* Buffer creation from user provided pointer */ DRM_ZOCL_USERPTR_BO, /* Get the buffer handle of given physical address */ DRM_ZOCL_GET_HOST_BO, /* Map buffer into application user space (no DMA is performed) */ DRM_ZOCL_MAP_BO, /* Sync buffer (like fsync) in the desired direction by using CPU cache flushing/invalidation */ DRM_ZOCL_SYNC_BO, /* Get information about the buffer such as physical address in the device, etc */ DRM_ZOCL_INFO_BO, /* Update host cached copy of buffer wih user's data */ DRM_ZOCL_PWRITE_BO, /* Update user's data with host cached copy of buffer */ DRM_ZOCL_PREAD_BO, /* Program the Device with specific xclbin image */ DRM_ZOCL_PCAP_DOWNLOAD, /* Send an execute job to a compute unit */ DRM_ZOCL_EXECBUF, /* Read the xclbin and map CUs */ DRM_ZOCL_READ_AXLF, /* Get the soft kernel command */ DRM_ZOCL_SK_GETCMD, /* Create the soft kernel */ DRM_ZOCL_SK_CREATE, /* Report the soft kernel state */ DRM_ZOCL_SK_REPORT, /* Get the information about Compute Unit such as physical address in the device */ DRM_ZOCL_INFO_CU, /* Open/Close context */ DRM_ZOCL_CTX, /* Error injection */ DRM_ZOCL_ERROR_INJECT, /* Request/Release AIE partition */ DRM_ZOCL_AIE_FD, /* Reset AIE Array */ DRM_ZOCL_AIE_RESET, /* Get the aie info command */ DRM_ZOCL_AIE_GETCMD, /* Put the aie info command */ DRM_ZOCL_AIE_PUTCMD, DRM_ZOCL_NUM_IOCTLS }; enum drm_zocl_sync_bo_dir { DRM_ZOCL_SYNC_BO_TO_DEVICE, DRM_ZOCL_SYNC_BO_FROM_DEVICE }; #define DRM_ZOCL_BO_FLAGS_HOST_BO (0x1 << 26) #define DRM_ZOCL_BO_FLAGS_COHERENT (0x1 << 27) #define DRM_ZOCL_BO_FLAGS_CMA (0x1 << 28) #define DRM_ZOCL_BO_FLAGS_SVM (0x1 << 29) #define DRM_ZOCL_BO_FLAGS_USERPTR (0x1 << 30) #define DRM_ZOCL_BO_FLAGS_EXECBUF (0x1 << 31) /** * struct drm_zocl_create_bo - Create buffer object * used with DRM_IOCTL_ZOCL_CREATE_BO ioctl * * @size: Requested size of the buffer object * @handle: bo handle returned by the driver * @flags: DRM_ZOCL_BO_XXX flags */ struct drm_zocl_create_bo { uint64_t size; uint32_t handle; uint32_t flags; }; /** * struct drm_zocl_userptr_bo - Create buffer object with user's pointer * used with DRM_IOCTL_ZOCL_USERPTR_BO ioctl * * @addr: Address of buffer allocated by user * @size: Requested size of the buffer object * @handle: bo handle returned by the driver * @flags: DRM_XOCL_BO_XXX flags */ struct drm_zocl_userptr_bo { uint64_t addr; uint64_t size; uint32_t handle; uint32_t flags; }; /** * struct drm_zocl_map_bo - Prepare a buffer object for mmap * used with DRM_IOCTL_ZOCL_MAP_BO ioctl * * @handle: bo handle * @pad: Unused * @offset: 'Fake' offset returned by the driver which can be used with POSIX mmap */ struct drm_zocl_map_bo { uint32_t handle; uint32_t pad; uint64_t offset; }; /** * struct drm_zocl_sync_bo - Synchronize the buffer in the requested direction * via cache flush/invalidation. * used with DRM_ZOCL_SYNC_BO ioctl. * * @handle: GEM object handle * @dir: DRM_ZOCL_SYNC_DIR_XXX * @offset: Offset into the object to write to * @size: Length of data to write */ struct drm_zocl_sync_bo { uint32_t handle; enum drm_zocl_sync_bo_dir dir; uint64_t offset; uint64_t size; }; /** * struct drm_zocl_info_bo - Obtain information about buffer object * used with DRM_IOCTL_ZOCL_INFO_BO ioctl * * @handle: GEM object handle * @size: Size of BO * @paddr: physical address */ struct drm_zocl_info_bo { uint32_t handle; uint64_t size; uint64_t paddr; }; /** * struct drm_zocl_host_bo - Get the buffer handle of given physical address * used with DRM_IOCTL_ZOCL_GET_HOST_BO ioctl * * @paddr: physical address * @size: Size of BO * @handle: GEM object handle */ struct drm_zocl_host_bo { uint64_t paddr; size_t size; uint32_t handle; }; /** * struct drm_zocl_pwrite_bo - Update bo with user's data * used with DRM_IOCTL_ZOCL_PWRITE_BO ioctl * * @handle: GEM object handle * @pad: Padding * @offset: Offset into the object to write to * @size: Length of data to write * @data_ptr: Pointer to read the data from (pointers not 32/64 compatible) */ struct drm_zocl_pwrite_bo { uint32_t handle; uint32_t pad; uint64_t offset; uint64_t size; uint64_t data_ptr; }; /** * struct drm_zocl_pread_bo - Read data from bo * used with DRM_IOCTL_ZOCL_PREAD_BO ioctl * * @handle: GEM object handle * @pad: Padding * @offset: Offset into the object to read from * @size: Length of data to wrreadite * @data_ptr: Pointer to write the data into (pointers not 32/64 compatible) */ struct drm_zocl_pread_bo { uint32_t handle; uint32_t pad; uint64_t offset; uint64_t size; uint64_t data_ptr; }; /** * struct drm_zocl_info_cu - Get information about Compute Unit (experimental) * used with DRM_IOCTL_ZOCL_INFO_CU ioctl * * @paddr: Physical address * @apt_idx: Aperture index * @cu_idx: CU index */ struct drm_zocl_info_cu { uint64_t paddr; int apt_idx; int cu_idx; }; enum drm_zocl_ctx_code { ZOCL_CTX_OP_ALLOC_CTX = 0, ZOCL_CTX_OP_FREE_CTX, ZOCL_CTX_OP_OPEN_GCU_FD }; #define ZOCL_CTX_NOOPS 0 #define ZOCL_CTX_SHARED (1 << 0) #define ZOCL_CTX_EXCLUSIVE (1 << 1) #define ZOCL_CTX_VERBOSE (1 << 2) #define ZOCL_CTX_VIRT_CU_INDEX 0xffffffff struct drm_zocl_ctx { uint64_t uuid_ptr; uint64_t uuid_size; uint32_t cu_index; uint32_t flags; // unused, in future it would return context id uint32_t handle; enum drm_zocl_ctx_code op; }; struct drm_zocl_aie_fd { uint32_t partition_id; uint32_t uid; int fd; }; struct drm_zocl_aie_reset { uint32_t partition_id; }; /** * Opcodes for the embedded scheduler provided by the client to the driver */ enum drm_zocl_execbuf_code { DRM_ZOCL_EXECBUF_RUN_KERNEL = 0, DRM_ZOCL_EXECBUF_RUN_KERNEL_XYZ, DRM_ZOCL_EXECBUF_PING, DRM_ZOCL_EXECBUF_DEBUG, }; /** * State of exec request managed by the kernel driver */ enum drm_zocl_execbuf_state { DRM_ZOCL_EXECBUF_STATE_COMPLETE = 0, DRM_ZOCL_EXECBUF_STATE_RUNNING, DRM_ZOCL_EXECBUF_STATE_SUBMITTED, DRM_ZOCL_EXECBUF_STATE_QUEUED, DRM_ZOCL_EXECBUF_STATE_ERROR, DRM_ZOCL_EXECBUF_STATE_ABORT, }; /** * struct drm_zocl_execbuf - Submit a command buffer for execution on a compute * unit (experimental) used with DRM_IOCTL_ZOCL_EXECBUF ioctl * * @ctx_id: Pass 0 * @exec_bo_handle: BO handle of command buffer formatted as ERT command */ struct drm_zocl_execbuf { uint32_t ctx_id; uint32_t exec_bo_handle; }; /* * enum drm_zocl_platform_flags - can be used for axlf bitstream */ enum drm_zocl_axlf_flags { DRM_ZOCL_PLATFORM_BASE = 0, DRM_ZOCL_PLATFORM_PR = (1 << 0), DRM_ZOCL_PLATFORM_FLAT = (1 << 1), }; /** * struct argument_info - Kernel argument information * * @name: argument name * @offset: argument offset in CU * @size: argument size in bytes * @dir: input or output argument for a CU */ struct argument_info { char name[32]; uint32_t offset; uint32_t size; uint32_t dir; }; /** * struct kernel_info - Kernel information * * @name: kernel name * @anums: number of argument * @args: argument array */ struct kernel_info { char name[64]; int anums; struct argument_info args[]; }; /** * struct drm_zocl_axlf - Read xclbin (AXLF) device image and map CUs (experimental) * used with DRM_IOCTL_ZOCL_READ_AXLF ioctl * * @za_xclbin_ptr: Pointer to xclbin (AXLF) object * @za_flags: platform flags * @za_ksize: size of kernels in bytes * @za_kernels: pointer of argument array **/ struct drm_zocl_axlf { struct axlf *za_xclbin_ptr; uint32_t za_flags; int za_ksize; char *za_kernels; }; #define ZOCL_MAX_NAME_LENGTH 32 #define ZOCL_MAX_PATH_LENGTH 255 #define AIE_INFO_SIZE 4096 /** * struct drm_zocl_sk_getcmd - Get the soft kernel command (experimental) * used with DRM_IOCTL_ZOCL_SK_GETCMD ioctl * * @opcode : opcode for the Soft Kernel Command Packet * @start_cuidx : start index of compute units * @cu_nums : number of compute units in program * @size : size in bytes of soft kernel image * @paddr : soft kernel image's physical address (little endian) * @name : symbol name of soft kernel */ struct drm_zocl_sk_getcmd { uint32_t opcode; uint32_t start_cuidx; uint32_t cu_nums; size_t size; uint64_t paddr; char name[ZOCL_MAX_NAME_LENGTH]; }; enum aie_info_code { GRAPH_STATUS = 1, }; /** * struct drm_zocl_aie_cmd - Get the aie command * used with DRM_IOCTL_ZOCL_AIE_GETCMD and DRM_IOCTL_ZOCL_AIE_PUTCMD ioctl * * @opcode : opcode for the Aie Command Packet * @size : size in bytes of info data * @info : information to transfer */ struct drm_zocl_aie_cmd { uint32_t opcode; uint32_t size; char info[AIE_INFO_SIZE]; }; /** * struct drm_zocl_sk_create - Create a soft kernel (experimental) * used with DRM_IOCTL_ZOCL_SK_CREATE ioctl * * @cu_idx : Compute unit index * @handle : Buffer object handle */ struct drm_zocl_sk_create { uint32_t cu_idx; uint32_t handle; }; /** * State of soft compute unit */ enum drm_zocl_scu_state { ZOCL_SCU_STATE_DONE, }; /** * struct drm_zocl_sk_report- Report the Soft Kernel State (experimental) * used with DRM_IOCTL_ZOCL_SK_REPORT ioctl * * @cu_idx : Compute unit index * @cu_state : State of the Soft Compute Unit */ struct drm_zocl_sk_report { uint32_t cu_idx; enum drm_zocl_scu_state cu_state; }; enum drm_zocl_err_ops { ZOCL_ERROR_OP_INJECT = 0, ZOCL_ERROR_OP_CLEAR_ALL }; struct drm_zocl_error_inject { enum drm_zocl_err_ops err_ops; uint16_t err_num; uint16_t err_driver; uint16_t err_severity; uint16_t err_module; uint16_t err_class; }; #define DRM_IOCTL_ZOCL_CREATE_BO DRM_IOWR(DRM_COMMAND_BASE + \ DRM_ZOCL_CREATE_BO, \ struct drm_zocl_create_bo) #define DRM_IOCTL_ZOCL_USERPTR_BO DRM_IOWR(DRM_COMMAND_BASE + \ DRM_ZOCL_USERPTR_BO, \ struct drm_zocl_userptr_bo) #define DRM_IOCTL_ZOCL_GET_HOST_BO DRM_IOWR(DRM_COMMAND_BASE + \ DRM_ZOCL_GET_HOST_BO, \ struct drm_zocl_host_bo) #define DRM_IOCTL_ZOCL_MAP_BO DRM_IOWR(DRM_COMMAND_BASE + \ DRM_ZOCL_MAP_BO, struct drm_zocl_map_bo) #define DRM_IOCTL_ZOCL_SYNC_BO DRM_IOWR(DRM_COMMAND_BASE + \ DRM_ZOCL_SYNC_BO, struct drm_zocl_sync_bo) #define DRM_IOCTL_ZOCL_INFO_BO DRM_IOWR(DRM_COMMAND_BASE + \ DRM_ZOCL_INFO_BO, struct drm_zocl_info_bo) #define DRM_IOCTL_ZOCL_PWRITE_BO DRM_IOWR(DRM_COMMAND_BASE + \ DRM_ZOCL_PWRITE_BO, \ struct drm_zocl_pwrite_bo) #define DRM_IOCTL_ZOCL_PREAD_BO DRM_IOWR(DRM_COMMAND_BASE + \ DRM_ZOCL_PREAD_BO, struct drm_zocl_pread_bo) #define DRM_IOCTL_ZOCL_EXECBUF DRM_IOWR(DRM_COMMAND_BASE + \ DRM_ZOCL_EXECBUF, struct drm_zocl_execbuf) #define DRM_IOCTL_ZOCL_READ_AXLF DRM_IOWR(DRM_COMMAND_BASE + \ DRM_ZOCL_READ_AXLF, struct drm_zocl_axlf) #define DRM_IOCTL_ZOCL_SK_GETCMD DRM_IOWR(DRM_COMMAND_BASE + \ DRM_ZOCL_SK_GETCMD, struct drm_zocl_sk_getcmd) #define DRM_IOCTL_ZOCL_SK_CREATE DRM_IOWR(DRM_COMMAND_BASE + \ DRM_ZOCL_SK_CREATE, struct drm_zocl_sk_create) #define DRM_IOCTL_ZOCL_SK_REPORT DRM_IOWR(DRM_COMMAND_BASE + \ DRM_ZOCL_SK_REPORT, struct drm_zocl_sk_report) #define DRM_IOCTL_ZOCL_INFO_CU DRM_IOWR(DRM_COMMAND_BASE + \ DRM_ZOCL_INFO_CU, struct drm_zocl_info_cu) #define DRM_IOCTL_ZOCL_CTX DRM_IOWR(DRM_COMMAND_BASE + \ DRM_ZOCL_CTX, struct drm_zocl_ctx) #define DRM_IOCTL_ZOCL_ERROR_INJECT DRM_IOWR(DRM_COMMAND_BASE + \ DRM_ZOCL_ERROR_INJECT, struct drm_zocl_error_inject) #define DRM_IOCTL_ZOCL_AIE_FD DRM_IOWR(DRM_COMMAND_BASE + \ DRM_ZOCL_AIE_FD, struct drm_zocl_aie_fd) #define DRM_IOCTL_ZOCL_AIE_RESET DRM_IOWR(DRM_COMMAND_BASE + \ DRM_ZOCL_AIE_RESET, struct drm_zocl_aie_reset) #define DRM_IOCTL_ZOCL_AIE_GETCMD DRM_IOWR(DRM_COMMAND_BASE + \ DRM_ZOCL_AIE_GETCMD, struct drm_zocl_aie_cmd) #define DRM_IOCTL_ZOCL_AIE_PUTCMD DRM_IOWR(DRM_COMMAND_BASE + \ DRM_ZOCL_AIE_PUTCMD, struct drm_zocl_aie_cmd) #endif dfx-mgr-xilinx_v2023.2/src/000077500000000000000000000000001446677152000155325ustar00rootroot00000000000000dfx-mgr-xilinx_v2023.2/src/CMakeLists.txt000066400000000000000000000051401446677152000202720ustar00rootroot00000000000000collector_create (PROJECT_LIB_SOURCES "${CMAKE_CURRENT_SOURCE_DIR}") collector_create (PROJECT_LIB_HEADERS "${CMAKE_CURRENT_SOURCE_DIR}") collect (PROJECT_LIB_DIRS "${CMAKE_CURRENT_BINARY_DIR}") collect (PROJECT_INC_DIRS "${CMAKE_CURRENT_BINARY_DIR}/include") collect (PROJECT_LIB_HEADERS accel.h) collect (PROJECT_LIB_HEADERS assert.h) collect (PROJECT_LIB_HEADERS dma.h) collect (PROJECT_LIB_HEADERS device.h) collect (PROJECT_LIB_HEADERS helper.h) collect (PROJECT_LIB_HEADERS print.h) collect (PROJECT_LIB_HEADERS shell.h) collect (PROJECT_LIB_HEADERS shm.h) collect (PROJECT_LIB_HEADERS dfxmgr_client.h) collect (PROJECT_LIB_HEADERS model.h) collect (PROJECT_LIB_HEADERS json-config.h) collect (PROJECT_LIB_HEADERS daemon_helper.h) collect (PROJECT_LIB_HEADERS conio.h) collect (PROJECT_LIB_SOURCES accel.c) collect (PROJECT_LIB_SOURCES assert.c) collect (PROJECT_LIB_SOURCES dma.c) collect (PROJECT_LIB_SOURCES device.c) collect (PROJECT_LIB_SOURCES shell.c) collect (PROJECT_LIB_SOURCES shm.c) collect (PROJECT_LIB_SOURCES dfxmgr_client.c) collect (PROJECT_LIB_SOURCES daemon_helper.c) add_subdirectory (sys) collector_list (_inc_dirs PROJECT_INC_DIRS) collector_list (_sources PROJECT_LIB_SOURCES) collector_list (_headers PROJECT_LIB_HEADERS) foreach (f ${_headers}) configure_file (${f} include/${PROJECT_NAME}/${f} @ONLY) # install (FILES ${CMAKE_CURRENT_BINARY_DIR}/include/${PROJECT_NAME}/${f} # DESTINATION include RENAME ${PROJECT_NAME}/${f}) if (${f} MATCHES "^[^/]*\\.h") collect (PROJECT_HDR_TESTS "acapd/${f}") endif (${f} MATCHES "^[^/]*\\.h") endforeach (f) include_directories (${_inc_dirs}) add_definitions (-DACAPD_INTERNAL) get_property (_ec_flags GLOBAL PROPERTY "PROJECT_EC_FLAGS") set (_deps "dfx") if (WITH_SHARED_LIB) set (_lib ${PROJECT_NAME}-shared) add_library (${_lib} SHARED ${_sources}) target_link_libraries (${_lib} ${_deps}) install (TARGETS ${_lib} LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR}) target_compile_options (${_lib} PUBLIC ${_ec_flags}) set_target_properties (${_lib} PROPERTIES OUTPUT_NAME "${PROJECT_NAME}" VERSION "${PROJECT_VERSION}" SOVERSION "${PROJECT_VERSION_MAJOR}" ) endif (WITH_SHARED_LIB) # Build a static library if so configured. if (WITH_STATIC_LIB) set (_lib ${PROJECT_NAME}-static) add_library (${_lib} STATIC ${_sources}) install (TARGETS ${_lib} ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR}) target_compile_options (${_lib} PUBLIC ${_ec_flags}) set_target_properties (${_lib} PROPERTIES OUTPUT_NAME "${PROJECT_NAME}" ) endif (WITH_STATIC_LIB) # vim: expandtab:ts=2:sw=2:smartindent dfx-mgr-xilinx_v2023.2/src/accel.c000066400000000000000000000210741446677152000167510ustar00rootroot00000000000000/* * Copyright (c) 2021, Xilinx Inc. and Contributors. All rights reserved. * * SPDX-License-Identifier: MIT */ #include #include #include #include #include #include #include #include #include #include #include #include #include #include void init_accel(acapd_accel_t *accel, acapd_accel_pkg_hd_t *pkg) { acapd_assert(accel != NULL); memset(accel, 0, sizeof(*accel)); accel->pkg = pkg; accel->rm_slot = -1; accel->status = ACAPD_ACCEL_STATUS_UNLOADED; } int acapd_parse_config(acapd_accel_t *accel, const char *shell_config) { int ret; /* Flat design don't have accel.json so do not parse */ if(!strcmp(accel->type,"SIHA_PL_DFX") || !strcmp(accel->type,"XRT_AIE_DFX")){ ret = sys_accel_config(accel); if (ret < 0) { DFX_ERR("failed to config accel"); return ACAPD_ACCEL_FAILURE; } } ret = acapd_shell_config(shell_config); if (ret < 0) { DFX_ERR("failed to config shell"); return ACAPD_ACCEL_FAILURE; } return ret; } static int get_fpga_flags(acapd_accel_t *accel) { char cmd[FILENAME_MAX]; snprintf(cmd, sizeof(cmd), "grep -sq external-fpga-config %s/*.dtbo", accel->sys_info.tmp_dir); return (system(cmd) == 0) ? DFX_EXTERNAL_CONFIG_EN : DFX_NORMAL_EN; } int load_accel(acapd_accel_t *accel, const char *shell_config, unsigned int async) { int ret; acapd_assert(accel != NULL); DFX_DBG("accel=%s shell_config=%s", accel->pkg->name, shell_config); ret = acapd_parse_config(accel, shell_config); if (ret < 0) { DFX_ERR("failed to parse config files"); return ACAPD_ACCEL_FAILURE; } ret = sys_needs_load_accel(accel); if (ret == 0) { DFX_DBG("no need to load accel"); return 0; } /* assert isolation before programming */ if (!strcmp(accel->type, "SIHA_PL_DFX")) { ret = acapd_shell_assert_isolation(accel); if (ret < 0) { DFX_ERR("failed to assert isolaction"); return ret; } } if (accel->is_cached == 0) { ret = sys_fetch_accel(accel, get_fpga_flags(accel)); if (ret != ACAPD_ACCEL_SUCCESS) { DFX_ERR("failed to fetch partial bistream"); return ret; } accel->is_cached = 1; } ret = sys_load_accel(accel, async); if (ret == ACAPD_ACCEL_SUCCESS) { accel->status = ACAPD_ACCEL_STATUS_INUSE; } else if (ret == ACAPD_ACCEL_INPROGRESS) { accel->status = ACAPD_ACCEL_STATUS_LOADING; } else { DFX_ERR("Failed to load partial bitstream ret %d", ret); accel->load_failure = ret; return ret; } if (accel->status == ACAPD_ACCEL_STATUS_INUSE && !strcmp(accel->type,"SIHA_PL_DFX")) { ret = acapd_shell_release_isolation(accel); if (ret != 0) { DFX_ERR("shell_release_isolation"); return ACAPD_ACCEL_FAILURE; } DFX_DBG("shell_release_isolation done"); } //ret = sys_load_accel_post(accel); return ret; } int accel_load_status(acapd_accel_t *accel) { acapd_assert(accel != NULL); if (accel->load_failure != ACAPD_ACCEL_SUCCESS) { return accel->load_failure; } else if (accel->status != ACAPD_ACCEL_STATUS_INUSE) { return ACAPD_ACCEL_INVALID; } else { return ACAPD_ACCEL_SUCCESS; } } int remove_base(int fpga_cfg_id) { if (fpga_cfg_id <= 0) { DFX_ERR("Invalid fpga_cfg_id: %d", fpga_cfg_id); return -1; } return sys_remove_base(fpga_cfg_id); } int remove_accel(acapd_accel_t *accel, unsigned int async) { acapd_assert(accel != NULL); if (accel->status == ACAPD_ACCEL_STATUS_UNLOADED) { DFX_ERR("accel is not loaded"); return ACAPD_ACCEL_SUCCESS; } else if (accel->status == ACAPD_ACCEL_STATUS_UNLOADING) { DFX_ERR("accel is unloading"); return ACAPD_ACCEL_INPROGRESS; } else { int ret; ret = sys_close_accel(accel); if (ret < 0) { DFX_ERR("failed to close accel"); return ACAPD_ACCEL_FAILURE; } ret = sys_needs_load_accel(accel); if (ret == 0) { DFX_DBG("no need to load accel"); accel->status = ACAPD_ACCEL_STATUS_UNLOADED; return ACAPD_ACCEL_SUCCESS; } else { if (!strcmp(accel->type,"SIHA_PL_DFX")) { ret = acapd_shell_assert_isolation(accel); if (ret < 0) { DFX_ERR("failed to assert isolaction"); return ret; } } ret = sys_remove_accel(accel, async); } if (ret == ACAPD_ACCEL_SUCCESS) { DFX_DBG("Succesfully removed accel"); accel->status = ACAPD_ACCEL_STATUS_UNLOADED; } else if (ret == ACAPD_ACCEL_INPROGRESS) { accel->status = ACAPD_ACCEL_STATUS_UNLOADING; } else { accel->status = ACAPD_ACCEL_STATUS_UNLOADING; } return ret; } } int acapd_accel_wait_for_data_ready(acapd_accel_t *accel) { /* TODO: always ready */ (void)accel; return 1; } int acapd_accel_open_channel(acapd_accel_t *accel) { acapd_assert(accel != NULL); acapd_assert(accel->chnls != NULL); for (int i = 0; i < accel->num_chnls; i++) { acapd_chnl_t *chnl = NULL; int ret; chnl = &accel->chnls[i]; acapd_debug("%s: opening chnnl\n", __func__); ret = acapd_dma_open(chnl); if (ret < 0) { acapd_perror("%s: failed to open channel.\n", __func__); return ret; } } return 0; } /* This function only reset AXIS DMA channel not the accelerator */ int acapd_accel_reset_channel(acapd_accel_t *accel) { int ret; acapd_assert(accel != NULL); acapd_assert(accel->chnls != NULL); ret = acapd_accel_open_channel(accel); if (ret < 0) { acapd_perror("%s: open channel fails.\n", __func__); return ret; } for (int i = 0; i < accel->num_chnls; i++) { acapd_chnl_t *chnl = NULL; chnl = &accel->chnls[i]; acapd_dma_stop(chnl); acapd_dma_reset(chnl); } return 0; } void *acapd_accel_get_reg_va(acapd_accel_t *accel, const char *name) { acapd_device_t *dev = NULL; acapd_assert(accel != NULL); if (name == NULL) { DFX_ERR("empty device name"); return NULL; } for (int i = 0; i < accel->num_ip_devs; i++) { if (strstr(accel->ip_dev[i].dev_name, name)) { dev = &accel->ip_dev[i]; break; } } if (dev == NULL) { DFX_ERR("failed to find device: %s", name); return NULL; } DFX_DBG("%s: match %s", name, dev->dev_name); if (dev->va == NULL) { int ret = acapd_device_open(dev); if (ret < 0) { DFX_ERR("failed to open dev %s", dev->dev_name); return NULL; } } return dev->va; } void sendBuffer(uint64_t size,int socket) { acapd_assert(size); sys_send_buff(size, socket); } void allocateBuffer(uint64_t size) { acapd_assert(size); sys_alloc_buffer(size); } void freeBuffer(uint64_t pa) { sys_free_buffer(pa); } void get_fds(acapd_accel_t *accel, int slot, int socket){ acapd_assert(accel != NULL); sys_get_fds(accel, slot, socket); } void get_shell_fd(int socket) { sys_get_fd(acapd_shell_fd(),socket); } void get_shell_clock_fd(int socket) { sys_get_fd(acapd_shell_clock_fd(),socket); } char *get_accel_path(const char *name, int slot) { char *base_path = malloc(sizeof(char)*1024); char *slot_path = malloc(sizeof(char)*1024); char *accel_path = malloc(sizeof(char)*1024); DIR *d, *base_d; struct dirent *dir, *base_dir; struct stat info; d = opendir(FIRMWARE_PATH); if (d == NULL) { acapd_perror("Directory %s not found\n",FIRMWARE_PATH); } while((dir = readdir(d)) != NULL) { if (dir->d_type == DT_DIR) { sprintf(base_path,"%s/%s", FIRMWARE_PATH, dir->d_name); base_d = opendir(base_path); while((base_dir = readdir(base_d)) != NULL) { if (base_dir->d_type == DT_DIR && !strcmp(base_dir->d_name, name)) { sprintf(accel_path,"%s/%s", base_path, base_dir->d_name); sprintf(slot_path,"%s/%s_slot%d", accel_path, base_dir->d_name,slot); if (stat(slot_path,&info) != 0) return NULL; if (info.st_mode & S_IFDIR){ acapd_debug("Reading accel.json from %s\n",slot_path); goto out; } } } } } return NULL; out: free(base_path); free(accel_path); return slot_path; } char * getAccelMetadata(char *package_name, int slot) { char filename[1024]; char *path; FILE *fptr; long numBytes; char *jsonData; int ret; path = get_accel_path(package_name, slot); if (path == NULL) { acapd_perror("No accel.json found for %s slot %d\n",package_name,slot); return NULL; } sprintf(filename,"%s/accel.json",path); fptr = fopen(filename, "r"); if (fptr == NULL){ acapd_debug("%s: Cannot open accel.json, %s\n",__func__,strerror(errno)); return NULL; } fseek(fptr, 0L, SEEK_END); numBytes = ftell(fptr); fseek(fptr, 0L, SEEK_SET); jsonData = (char *)calloc(numBytes, sizeof(char)); if (jsonData == NULL) return NULL; ret = fread(jsonData, sizeof(char), numBytes, fptr); if (ret < numBytes) acapd_perror("%s: Error reading Accel.json\n",__func__); fclose(fptr); return jsonData; } dfx-mgr-xilinx_v2023.2/src/accel.h000066400000000000000000000103021446677152000167460ustar00rootroot00000000000000/* * Copyright (c) 2021, Xilinx Inc. and Contributors. All rights reserved. * * SPDX-License-Identifier: MIT */ /* * @file accel.h * @brief accelerator definition. */ #ifndef _ACAPD_ACCEL_H #define _ACAPD_ACCEL_H #ifdef __cplusplus extern "C" { #endif #include #include #include #include #include #include #define ACAPD_ACCEL_STATUS_UNLOADED 0U #define ACAPD_ACCEL_STATUS_LOADING 1U #define ACAPD_ACCEL_STATUS_INUSE 2U #define ACAPD_ACCEL_STATUS_UNLOADING 3U #define ACAPD_ACCEL_SUCCESS 0 #define ACAPD_ACCEL_FAILURE (-1) #define ACAPD_ACCEL_TIMEDOUT (-2) #define ACAPD_ACCEL_MISMATCHED (-3) #define ACAPD_ACCEL_RSCLOCKED (-4) #define ACAPD_ACCEL_NOTSUPPORTED (-5) #define ACAPD_ACCEL_INVALID (-6) #define ACAPD_ACCEL_LOAD_INUSE (-7) #define ACAPD_ACCEL_INPROGRESS 1 #define ACAPD_ACCEL_PKG_TYPE_NONE 0U #define ACAPD_ACCEL_PKG_TYPE_TAR_GZ 1U #define ACAPD_ACCEL_PKG_TYPE_LAST 2U #define FIRMWARE_PATH "/lib/firmware/xilinx" /** * @brief accel package information structure */ typedef struct { uint32_t type; /**< type of package element */ char name[128]; /**< name of the package element */ char *path; /** path on the filesystem */ uint64_t size; /**< size of package element */ uint32_t is_end; /**< if it is the end of package */ } acapd_accel_pkg_hd_t; typedef struct { int socket_d; /* stream socket desc*/ int drm_fd; int fd; uint32_t handle; uint64_t PA; uint64_t size; } acapd_buffer_t; /** * @brief accel structure */ typedef struct { acapd_accel_pkg_hd_t *pkg; /**< pointer to the package */ acapd_accel_sys_t sys_info; /**< system specific accel information */ char type[32]; /**< type of the accelarator */ unsigned int status; /**< status of the accelarator */ unsigned int is_cached; /**< if the accelerator is cached */ int load_failure; /**< load failure */ int num_ip_devs; /**< number of accelerator devices */ acapd_device_t *shell_dev; /**< shell device reg structure */ acapd_device_t *ip_dev; /**< accelerator IPs reg structure */ int rm_slot; /**< Reconfiguration module slot */ int num_chnls; /**< number of channels */ acapd_chnl_t *chnls; /**< list of channels */ } acapd_accel_t; acapd_accel_pkg_hd_t *acapd_alloc_pkg(size_t size); /* User applicaiton will need to allocate large enough memory for the package. * Library is not going to allocate the memory for it. This function is supposed * to be replaced by a host tool. */ int acapd_config_pkg(acapd_accel_pkg_hd_t *pkg, uint32_t type, char *name, size_t size, void *data, int is_end); void init_accel(acapd_accel_t *accel, acapd_accel_pkg_hd_t *pkg); int load_accel(acapd_accel_t *accel, const char* shell_config, unsigned int async); int acapd_accel_config(acapd_accel_t *accel); int accel_load_status(acapd_accel_t *accel); int acapd_accel_wait_for_data_ready(acapd_accel_t *accel); void *acapd_accel_get_reg_va(acapd_accel_t *accel, const char *name); int remove_accel(acapd_accel_t *accel, unsigned int async); int remove_base(int fpga_cfg_id); int acapd_accel_open_channel(acapd_accel_t *accel); int acapd_accel_reset_channel(acapd_accel_t *accel); void get_fds(acapd_accel_t *accel, int slot, int socket); void allocateBuffer(uint64_t size); void sendBuffer(uint64_t size, int socket); void freeBuffer(uint64_t pa); void get_shell_fd(int socket); void get_shell_clock_fd(int socket); char * getAccelMetadata(char *package_name, int slot); #ifdef ACAPD_INTERNAL int sys_needs_load_accel(acapd_accel_t *accel); int sys_accel_config(acapd_accel_t *accel); int sys_fetch_accel(acapd_accel_t *accel, int flags); int sys_load_accel(acapd_accel_t *accel, unsigned int async); int sys_load_accel_post(acapd_accel_t *accel); int sys_close_accel(acapd_accel_t *accel); int sys_remove_accel(acapd_accel_t *accel, unsigned int async); int sys_remove_base(int fpga_cfg_id); acapd_buffer_t *sys_alloc_buffer(uint64_t size); int sys_free_buffer(uint64_t pa); int sys_send_buff(uint64_t size, int socket); int sys_print_buffers(); int sys_get_fds(acapd_accel_t *accel, int fd, int socket); void sys_get_fd(int fd, int socket); #endif /* ACAPD_INTERNAL */ #ifdef __cplusplus } #endif #endif /* _ACAPD_ACCEL_H */ dfx-mgr-xilinx_v2023.2/src/assert.c000066400000000000000000000005021446677152000171740ustar00rootroot00000000000000/* * Copyright (c) 2021, Xilinx Inc. and Contributors. All rights reserved. * * SPDX-License-Identifier: MIT */ #include #include void acapd_assert(unsigned int cond) { #ifdef DEBUG if ((cond) == 0) { printf("%s, %d\n", __FILE__, __LINE__); while(1); } #else (void)cond; #endif } dfx-mgr-xilinx_v2023.2/src/assert.h000066400000000000000000000006331446677152000172060ustar00rootroot00000000000000/* * Copyright (c) 2021, Xilinx Inc. and Contributors. All rights reserved. * * SPDX-License-Identifier: MIT */ /* * @file assert.h * @brief assert definition. */ #ifndef _ACAPD_ASSERT_H #define _ACAPD_ASSERT_H #include #define _unused(x) ((void)(x)) #ifdef __cplusplus extern "C" { #endif void acapd_assert(unsigned int cond); #ifdef __cplusplus } #endif #endif /* _ACAPD_COMMON_H */ dfx-mgr-xilinx_v2023.2/src/conio.h000066400000000000000000000012721446677152000170140ustar00rootroot00000000000000#include #include #include /* reads from keypress, doesn't echo */ int getch(void) { struct termios oldattr, newattr; int ch; tcgetattr( STDIN_FILENO, &oldattr ); newattr = oldattr; newattr.c_lflag &= ~( ICANON | ECHO ); tcsetattr( STDIN_FILENO, TCSANOW, &newattr ); ch = getchar(); tcsetattr( STDIN_FILENO, TCSANOW, &oldattr ); return ch; } /* reads from keypress, echoes */ int getche(void) { struct termios oldattr, newattr; int ch; tcgetattr( STDIN_FILENO, &oldattr ); newattr = oldattr; newattr.c_lflag &= ~( ICANON ); tcsetattr( STDIN_FILENO, TCSANOW, &newattr ); ch = getchar(); tcsetattr( STDIN_FILENO, TCSANOW, &oldattr ); return ch; } dfx-mgr-xilinx_v2023.2/src/daemon.conf000066400000000000000000000001461446677152000176450ustar00rootroot00000000000000{ "firmware_location": ["/lib/firmware/xilinx"], "default_accel":"/etc/dfx-mgrd/default_firmware" } dfx-mgr-xilinx_v2023.2/src/daemon_helper.c000066400000000000000000001170371446677152000205110ustar00rootroot00000000000000/* * Copyright (c) 2021, Xilinx Inc. and Contributors. All rights reserved. * * SPDX-License-Identifier: MIT */ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include struct daemon_config config; struct watch *active_watch = NULL; struct basePLDesign *base_designs = NULL; static int inotifyFd; platform_info_t platform; sem_t mutex; void firmware_dir_walk(void); struct watch { int wd; char name[64]; char path[WATCH_PATH_LEN]; char parent_name[64]; char parent_path[WATCH_PATH_LEN]; }; struct basePLDesign *findBaseDesign(const char *name) { int i,j; for (i = 0; i < MAX_WATCH; i++) { if (base_designs[i].base_path[0] != '\0') { if(!strcmp(base_designs[i].name, name)) { DFX_DBG("Found base design %s", base_designs[i].name); return &base_designs[i]; } for (j = 0; j < RP_SLOTS_MAX; j++) { if(!strcmp(base_designs[i].accel_list[j].name, name)) { DFX_DBG("accel %s in base %s", name, base_designs[i].name); return &base_designs[i]; } } } } DFX_ERR("No accel found for %s", name); return NULL; } struct basePLDesign *findBaseDesign_path(const char *path) { int i,j; for (i = 0; i < MAX_WATCH; i++) { if (base_designs[i].base_path[0] != '\0') { if(!strcmp(base_designs[i].base_path, path)) { DFX_DBG("Found base design %s", base_designs[i].base_path); return &base_designs[i]; } for (j = 0; j < RP_SLOTS_MAX; j++) { if(!strcmp(base_designs[i].accel_list[j].path, path)) { DFX_DBG("accel %s in base %s", path, base_designs[i].base_path); return &base_designs[i]; } } } } DFX_ERR("No base design or accel found for %s", path); return NULL; } /* * getRMInfo is a function intended to be able to read the presently * loaded RMs. Rename to saveRMinfo()? */ void getRMInfo() { FILE *fptr; int i; struct basePLDesign *base = platform.active_base; if(base == NULL || base->slots == NULL) { DFX_ERR("No design currently loaded"); return; } fptr = fopen("/home/root/rm_info.txt","w"); if (fptr == NULL) { DFX_ERR("Couldn't create /home/root/rm_info.txt"); return; } for (i = 0; i < base->num_pl_slots; i++) fprintf(fptr, "%d %s\n", i, base->slots[i] ? "used" : "GREY"); fclose(fptr); } /* * Update Vitis AI Runtime (VART) env */ void update_env(char *path) { DIR *FD; struct dirent *dir; int len, ret; char *str; char cmd[128]; DFX_DBG("%s", path); FD = opendir(path); if (FD) { while ((dir = readdir(FD)) != NULL) { len = strlen(dir->d_name); if (len > 7) { if (!strcmp(dir->d_name + (len - 7), ".xclbin") || !strcmp(dir->d_name + (len - 7), ".XCLBIN")) { str = (char *) calloc((len + strlen(path) + 1), sizeof(char)); sprintf(str, "%s/%s", path, dir->d_name); sprintf(cmd,"echo \"firmware: %s\" > /etc/vart.conf",str); free(str); DFX_DBG("system %s", cmd); ret = system(cmd); if (ret) DFX_ERR("%s", cmd); } } } closedir(FD); } } int load_accelerator(const char *accel_name) { int i, ret; char path[1024]; char shell_path[600]; acapd_accel_t *pl_accel = (acapd_accel_t *)calloc(sizeof(acapd_accel_t), 1); acapd_accel_pkg_hd_t *pkg = (acapd_accel_pkg_hd_t *)calloc(sizeof(acapd_accel_pkg_hd_t),1); struct basePLDesign *base = findBaseDesign(accel_name); slot_info_t *slot = (slot_info_t *)malloc(sizeof(slot_info_t)); accel_info_t *accel_info = NULL; slot->accel = NULL; if(base == NULL) { DFX_ERR("No package found for %s", accel_name); goto out; } sprintf(shell_path,"%s/shell.json",base->base_path); /* Flat shell design are treated as with one slot */ if (!strcmp(base->type,"XRT_FLAT") || !strcmp(base->type,"PL_FLAT")) { if (base->slots == NULL) base->slots = calloc(base->num_pl_slots + base->num_aie_slots, sizeof(slot_info_t *)); if(platform.active_base != NULL && platform.active_base->active > 0) { DFX_ERR("Remove previously loaded accelerator, no empty slot"); goto out; } sprintf(pkg->name,"%s",accel_name); pkg->path = base->base_path; pkg->type = ACAPD_ACCEL_PKG_TYPE_NONE; init_accel(pl_accel, pkg); strncpy(pl_accel->sys_info.tmp_dir, pkg->path, sizeof(pl_accel->sys_info.tmp_dir) - 1); strcpy(pl_accel->type,"XRT_FLAT"); DFX_PR("load flat shell from %s", pkg->path); ret = load_accel(pl_accel, shell_path, 0); if (ret < 0){ DFX_ERR("load_accel %s", accel_name); base->active = 0; goto out; } pl_accel->rm_slot = 0; base->fpga_cfg_id = pl_accel->sys_info.fpga_cfg_id; base->active += 1; slot->accel = pl_accel; slot->is_aie = 0; base->slots[0] = slot; platform.active_base = base; /* VART libary for SOM desings needs .xclbin path to be written to a file*/ if(!strcmp(base->type,"XRT_FLAT")) update_env(pkg->path); return 0; } for (i = 0; i < RP_SLOTS_MAX; i++){ if(!strcmp(base->accel_list[i].name, accel_name)) { accel_info = &base->accel_list[i]; DFX_DBG("Found accel %s base %s parent %s", accel_info->path, base->base_path, accel_info->parent_path); } } /* For SIHA slotted architecture */ if(!strcmp(base->type,"PL_DFX")) { if (platform.active_base != NULL && !platform.active_base->active && strcmp(platform.active_base->base_path, accel_info->parent_path)) { DFX_PR("All slots for base are empty, loading new base design"); remove_base(platform.active_base->fpga_cfg_id); free(platform.active_base->slots); platform.active_base->slots = NULL; platform.active_base = NULL; } else if(platform.active_base != NULL && platform.active_base->active > 0 && strcmp(platform.active_base->base_path, accel_info->parent_path)) { DFX_ERR("Active base design doesn't match this accel base"); goto out; } if (platform.active_base == NULL) { sprintf(pkg->name,"%s",base->name); pkg->path = base->base_path; pkg->type = ACAPD_ACCEL_PKG_TYPE_NONE; if (base->load_base_design) { init_accel(pl_accel, pkg); strncpy(pl_accel->sys_info.tmp_dir, pkg->path, sizeof(pl_accel->sys_info.tmp_dir) - 1); strcpy(pl_accel->type,"PL_DFX"); DFX_PR("load from %s", pkg->path); ret = load_accel(pl_accel, shell_path, 0); if (ret < 0){ DFX_ERR("load_accel %s", accel_name); base->active = 0; goto out; } DFX_PR("Loaded %s successfully", base->name); base->fpga_cfg_id = pl_accel->sys_info.fpga_cfg_id; } if (base->slots == NULL) base->slots = calloc(base->num_pl_slots + base->num_aie_slots, sizeof(slot_info_t *)); platform.active_base = base; } /* * Check if base UID matches the parent_uid in accel_info */ DFX_DBG("base(%s).uid = %d does %s match accel(%s).pid = %d", base->name, base->uid, base->uid == accel_info->pid ? "" : "NOT", accel_info->name, accel_info->pid); for (i = 0; i < (base->num_pl_slots + base->num_aie_slots); i++) { DFX_DBG("Finding empty slot for %s i %d", accel_name, i); if (base->slots[i] == NULL){ sprintf(path,"%s/%s_slot%d", accel_info->path, accel_info->name,i); if (access(path,F_OK) != 0){ continue; } strcpy(slot->name, accel_name); if (!strcmp(accel_info->accel_type,"XRT_AIE_DFX")) { DFX_ERR("%s: XRT_AIE_DFX unsupported", accel_name); goto out; } slot->is_aie = 0; strcpy(pkg->name, accel_name); pkg->path = path; pkg->type = ACAPD_ACCEL_PKG_TYPE_NONE; init_accel(pl_accel, pkg); /* Set rm_slot before load_accel() so isolation for appropriate slot can be applied*/ pl_accel->rm_slot = i; strcpy(pl_accel->type,accel_info->accel_type); strncpy(pl_accel->sys_info.tmp_dir, pkg->path, sizeof(pl_accel->sys_info.tmp_dir) - 1); DFX_PR("load from %s", pkg->path); ret = load_accel(pl_accel, shell_path, 0); if (ret < 0){ DFX_ERR("load_accel %s", accel_name); goto out; } platform.active_base->active += 1; slot->accel = pl_accel; base->slots[i] = slot; DFX_PR("Loaded %s successfully to slot %d", pkg->name, i); return i; } } if (i >= (base->num_pl_slots + base->num_aie_slots)) DFX_ERR("No empty slot for %s", accel_name); } else { DFX_ERR("Check the supported type of base/accel"); } out: free(slot); free(pl_accel); free(pkg); return -1; } static int remove_accel_base(void) { struct basePLDesign *base = platform.active_base; int ret = -1; if (!base) DFX_PR("No base"); else if (strcmp(base->type, "PL_DFX")) DFX_PR("Invalid base type: %s", base->type); else if (base->active) DFX_PR("Can't remove active base PL design: %s", base->name); else { DFX_PR("Unload base: %s", base->name); ret = remove_base(base->fpga_cfg_id); if (ret == 0) { free(base->slots); base->slots = NULL; platform.active_base = NULL; } } return ret; } int remove_accelerator(int slot) { struct basePLDesign *base = platform.active_base; acapd_accel_t *accel; int ret; /* slot -1 means remove base PL design */ if (slot == -1) return remove_accel_base(); if (!base || slot < 0 || base->active < slot || !base->slots[slot]) { DFX_ERR("No Accel or invalid slot %d", slot); return -1; } if (base->slots[slot]->is_aie){ free(base->slots[slot]); base->slots[slot] = NULL; platform.active_base->active -= 1; return 0; } accel = base->slots[slot]->accel; DFX_PR("Removing accel %s from slot %d", accel->pkg->name, slot); ret = remove_accel(accel, 0); free(accel->pkg); free(accel); free(base->slots[slot]); base->slots[slot] = NULL; platform.active_base->active -= 1; return ret; } void sendBuff(uint64_t size) { DFX_PR("buffer size %lu", size); //sendBuffer(size, socket_d); } void allocBuffer(uint64_t size) { DFX_PR("buffer size %lu", size); allocateBuffer(size); } void freeBuff(uint64_t pa) { DFX_DBG("free buffer PA %lu", pa); freeBuffer(pa); } int getFD(int slot, char *name) { struct basePLDesign *base = platform.active_base; if(base == NULL || base->slots == NULL){ DFX_ERR("No active design"); return -1; } if ( slot >= base->num_pl_slots || !base->slots[slot]) return -1; acapd_accel_t *accel = base->slots[slot]->accel; if (accel == NULL){ DFX_ERR("No Accel in slot %d", slot); return -1; } for (int i = 0; i < accel->num_ip_devs; i++) if (strstr(accel->ip_dev[i].dev_name, name)) return accel->ip_dev[i].id; // Check if the name matches one of the shell devices return dfx_shell_fd_by_name(name); } int dfx_getFDs(int slot, int *fd) { struct basePLDesign *base = platform.active_base; if(base == NULL){ DFX_ERR("No active design"); return -1; } acapd_accel_t *accel = base->slots[slot]->accel; if (accel == NULL){ DFX_ERR("No Accel in slot %d", slot); return -1; } fd[0] = accel->ip_dev[2*slot].id; fd[1] = accel->ip_dev[2*slot+1].id; DFX_PR("Daemon slot %d accel_config %d d_hls %d", slot, fd[0], fd[1]); return 0; } void getShellFD() { //get_shell_fd(socket_d); } void getClockFD() { //get_shell_clock_fd(socket_d); } /* * list_accel_uio list uio device name and its path * * Note: dev_name + path < 80 char, see: acapd_device_t * and device_name limits in json. Reduce buf sise by * one line (80 char) to prevent buffer overrun. */ void list_accel_uio(int slot, char *buf, size_t sz) { struct basePLDesign *base = platform.active_base; acapd_accel_t *accel; char *end = buf + sz - 80; char *p = buf; int i; if(base == NULL || base->slots == NULL) p += sprintf(p, "No active design\n"); else if ( slot >= base->num_pl_slots || !base->slots[slot]) p += sprintf(p, "slot %d is not used or invalid\n", slot); else if ( (accel = base->slots[slot]->accel) == NULL) p += sprintf(p, "No Accel in slot %d\n", slot); if (p != buf) return; for (i = 0; i < accel->num_ip_devs && p < end; i++) { char *dname = accel->ip_dev[i].dev_name; if (dname) p += sprintf(p, "%-30s %s\n", dname, accel->ip_dev[i].path); } dfx_shell_uio_list(p, end - p); } char * get_accel_uio_by_name(int slot, const char *name) { struct basePLDesign *base = platform.active_base; acapd_accel_t *accel; // NULL if no active design, slot is not used or invalid if(!base || !base->slots || slot >= base->num_pl_slots || !base->slots[slot]) return NULL; accel = base->slots[slot]->accel; if (!accel) return NULL; for (int i = 0; i < accel->num_ip_devs; i++) if (strstr(accel->ip_dev[i].dev_name, name)) return accel->ip_dev[i].path; // Check if the name matches one of the shell devices return dfx_shell_uio_by_name(name); } /* * the s2mm config offset is 0; mm2s - 0x10000 * TBD: find a sutable header file for DM_*_OFFT and data_mover_cfg */ #define DM_S2MM_OFFT 0 #define DM_MM2S_OFFT 0x10000 struct data_mover_cfg { uint32_t dm_cr; /**< 0: Control signals */ uint32_t dm_gier; /**< 4: Global Interrupt Enable Reg */ uint32_t dm_iier; /**< 8: IP Interrupt Enable Reg */ uint32_t dm_iisr; /**< c: IP Interrupt Status Reg */ uint32_t dm_addr_lo; /**< 10: Data signal of mem_V[31:0] */ uint32_t dm_addr_hi; /**< 14: Data signal of mem_V[63:31] */ uint32_t dm_x18; /**< 18: reserved */ uint32_t dm_size_lo; /**< 1c: Data signal of size_V[31:0] */ uint32_t dm_x20; /**< 20: reserved */ uint32_t dm_tid; /**< 24: Data signal of tid_V[7:0] */ }; static int dm_format(char *buf, struct data_mover_cfg *p_dm) { struct basePLDesign *base = platform.active_base; uint64_t addr = p_dm->dm_addr_hi; int s, slot = '-'; addr = addr << 32 | p_dm->dm_addr_lo; for (s = 0; s < base->num_pl_slots; s++) if (base->inter_rp_comm[s] == addr) { slot = s + '0'; break; } return sprintf(buf, ": addr[%c]=%#12lx sz=%#8x\n", slot, addr, p_dm->dm_size_lo); } #define DMCFG(p, f) (*(uint32_t *)((p) + offsetof(struct data_mover_cfg, f))) /** * siha_ir_buf_list - list DMs configuration * @sz: the size of the buf * @buf: buffer to put the DMs configuration * * Some of the bits in data_mover_cfg are Clear-On-Read, e.g.: * dm_cr:1 (bit 1) * Do not read all of the struct data_mover_cfg as in * memcpy(&dm_cfg, reg + DM_MM2S_OFFT, sizeof(dm_cfg)); * This causes user application to hang. * * Returns: 0 on error or the size of the buffer to send to the client */ int siha_ir_buf_list(uint32_t sz, char *buf) { struct basePLDesign *base = platform.active_base; struct data_mover_cfg dm_cfg; char *p = buf; uint8_t slot; if (sz > (1<<15) || !buf) { /* the sz should be < struct_message.data[32*1024] */ DFX_ERR("sz,buf = %u,%p", sz, buf); return 0; } if (!base || !base->slots || strcmp(base->type, "PL_DFX")) { p += sprintf(p, "No base, slots, or not a PL_DFX base: %s", base ? base->name : "no_base"); return (p > buf) ? p + 1 - buf : 0; } memset(&dm_cfg, 0, sizeof(dm_cfg)); for (slot = 0; slot < base->num_pl_slots && base->slots[slot] && base->slots[slot]->accel && (p < buf + sz); slot++) { acapd_accel_t *accel = base->slots[slot]->accel; void *reg = acapd_accel_get_reg_va(accel, "rm_comm_box"); p += sprintf(p, "DataMover[%hhu]: %p\n", slot, reg); /* dm_cr:1 (bit 1) is Clear-on-Read: do not read it */ if (reg) { uint64_t cr = (uint64_t)reg + DM_MM2S_OFFT; dm_cfg.dm_addr_lo = DMCFG(cr, dm_addr_lo); dm_cfg.dm_addr_hi = DMCFG(cr, dm_addr_hi); dm_cfg.dm_size_lo = DMCFG(cr, dm_size_lo); p += sprintf(p, " mm2s[%hhu]", slot); p += dm_format(p, &dm_cfg); cr = (uint64_t)reg + DM_S2MM_OFFT; dm_cfg.dm_addr_lo = DMCFG(cr, dm_addr_lo); dm_cfg.dm_addr_hi = DMCFG(cr, dm_addr_hi); dm_cfg.dm_size_lo = DMCFG(cr, dm_size_lo); p += sprintf(p, " s2mm[%hhu]", slot); p += dm_format(p, &dm_cfg); } } return (p > buf) ? p + 1 - buf : 0; } /** * siha_ir_buf - src outputs to the slot dst IR-buffer * @src: src slot writes to dst IR-buffer * @des: dst slot reads from dst IR-buffer * * Inter-RP buffer addrs are from shell.json. See rp_comms_interconnect * * Returns: 0 if connected successfully; non-0 otherwise */ static int siha_ir_buf(acapd_accel_t *src, acapd_accel_t *dst) { void *src_dm = acapd_accel_get_reg_va(src, "rm_comm_box"); void *dst_dm = acapd_accel_get_reg_va(dst, "rm_comm_box"); struct basePLDesign *base = platform.active_base; struct data_mover_cfg *p_src, *q_dst; uint32_t ir_buf_lo, ir_buf_hi; int dst_slot = dst->rm_slot; if (dst_slot < 0 || dst_slot > base->num_pl_slots - 1) { DFX_ERR("dst_slot=%d", dst_slot); return -1; } if (!src_dm || !dst_dm) { DFX_ERR("rm_comm_box src,dst = %p,%p", src_dm, dst_dm); return -1; } ir_buf_lo = base->inter_rp_comm[dst_slot] & 0xFFFFFFFF; ir_buf_hi = base->inter_rp_comm[dst_slot] >> 32; DFX_DBG("src,dst=%u,%u addr=%p", src->rm_slot, dst_slot, (void *)base->inter_rp_comm[dst_slot]); /* set s2mm in src_dm to write to dst IR-buf */ /* set mm2s in dst_dm to read from its own IR-buf */ p_src = (struct data_mover_cfg *)(src_dm + DM_S2MM_OFFT); q_dst = (struct data_mover_cfg *)(dst_dm + DM_MM2S_OFFT); p_src->dm_addr_lo = q_dst->dm_addr_lo = ir_buf_lo; p_src->dm_addr_hi = q_dst->dm_addr_hi = ir_buf_hi; /* * The app should set the size and the ap_start bit: * p_src->dm_size_lo = q_dst->dm_size_lo = input_size; * q_dst->dm_cr = 1; * p_src->dm_cr = 1; */ return 0; } /** * slot_seq_init copy only 0-9 into slot_seq (filter delimiters) */ #ifndef BIT #define BIT(N) (1U << (N)) #endif static int slot_seq_init(char *slot_seq, char *buf) { int num_pl_slots = platform.active_base->num_pl_slots; uint32_t no_dup = 0; int i, sz; for (sz = i = 0; i < RP_SLOTS_MAX; i++) { int c = buf[i] - '0'; if (c >= 0 && c <= num_pl_slots) { if (no_dup & BIT(c)) { DFX_ERR("repeated slot %d in %s", c, buf); return -1; } no_dup |= BIT(c); slot_seq[sz++] = c; } } return sz; } /** * siha_ir_buf_set - Set up Inter-RM buffers for I/O between slots * @slot_seq: user input array of slot IDs to connect * * Check if the slot_seq is valid, i.e.: * - 1 < sz < base->num_pl_slots * - it's a permutation w/o repetitions. Same as in nPk - "n permute k". * - the requested slots are loaded * * Returns: 0 if connected successfully; non-0 otherwise */ int siha_ir_buf_set(char *user_slot_seq) { struct basePLDesign *base = platform.active_base; // acapd_accel_t *accel_src, *accel_dst; uint8_t slot0, slot; char slot_seq[RP_SLOTS_MAX]; int i, sz; // NULL if no active design, slot is not used or invalid if (!base || !base->slots || strcmp(base->type, "PL_DFX")) { DFX_ERR("No base, slots, or not a PL_DFX base: %s", base ? base->name : "no_base"); return -1; } sz = slot_seq_init(slot_seq, user_slot_seq); if (sz < 2 || sz > base->num_pl_slots) { DFX_ERR("invalid sz: %d or sequence: %s", sz, user_slot_seq); return -1; } for (slot0 = 0xff, slot = i = 0; i < sz; i++) { slot = slot_seq[i]; DFX_DBG("s,d=%d,%d", (int)slot0, (int)slot); if (slot > base->num_pl_slots || !base->slots[slot]) { DFX_ERR("No accel in slot %u", slot); return -1; } if (slot0 != 0xff && slot0 != slot) { int rc = siha_ir_buf(base->slots[slot0]->accel, base->slots[slot]->accel); if (rc) { DFX_ERR("slot: %u,%u", slot0, slot); return -1; } } slot0 = slot; } return 0; } /* * pid_error - return 1 if PL_DFX IDs do not match, 0 otherwise * @base: base to get its uid * @accel_idx: index of the accel: its pid should match uid of the base * * Returns: 0 for *FLAT shells, or if id's are non-zero and match */ static int pid_error(struct basePLDesign *base, int accel_idx) { int uid = base->uid; int pid = base->accel_list[accel_idx].pid; return (!strcmp(base->type, "XRT_FLAT") || !strcmp(base->type, "PL_FLAT") || (uid && pid && (uid == pid))) ? 0 : 1; } char *listAccelerators() { int i,j; uint8_t slot; char msg[330]; /* compiler warning if 326 bytes or less */ char res[8*1024]; char show_slots[16]; const char format[] = "%30s%16s%30s%4s%16s%16s%16s\n"; memset(res,0, sizeof(res)); firmware_dir_walk(); sprintf(msg, format, "Accelerator", "Accel_type", "Base", "Pid", "Base_type", "#slots(PL+AIE)", "Active_slot"); strcat(res,msg); for (i = 0; i < MAX_WATCH; i++) { if (base_designs[i].base_path[0] != '\0' && base_designs[i].num_pl_slots > 0) { for (j = 0; j < RP_SLOTS_MAX; j++) { if (base_designs[i].accel_list[j].path[0] != '\0') { char active_slots[16] = ""; /* * Internally flat shell is treated as one slot to make * the code generic and save info of the active design */ sprintf(show_slots, "(%d+%d)", !strcmp(base_designs[i].type, "XRT_FLAT") || !strcmp(base_designs[i].type, "PL_FLAT") ? 0 : base_designs[i].num_pl_slots, base_designs[i].num_aie_slots); if (base_designs[i].active) { char tmp[5]; for(slot = 0; slot < (base_designs[i].num_pl_slots + base_designs[i].num_aie_slots); slot++) { if (base_designs[i].slots[slot] != NULL && base_designs[i].slots[slot]->is_aie && !strcmp(base_designs[i].slots[slot]->name, base_designs[i].accel_list[j].name)) { sprintf(tmp,"%d,",slot); strcat(active_slots,tmp); } else if (base_designs[i].slots[slot] != NULL && !base_designs[i].slots[slot]->is_aie && !strcmp(base_designs[i].slots[slot]->accel->pkg->name, base_designs[i].accel_list[j].name)) { sprintf(tmp,"%d,",slot); strcat(active_slots,tmp); } } } sprintf(msg, format, base_designs[i].accel_list[j].name, base_designs[i].accel_list[j].accel_type, base_designs[i].name, pid_error(&base_designs[i], j) ? "err" : "ok", base_designs[i].type, show_slots, active_slots[0] ? active_slots : "-1"); strcat(res, msg); } } } } return strdup(res); } void add_to_watch(int wd, char *name, char *path, char *parent_name, char *parent_path) { int i; for (i = 0; i < MAX_WATCH; i++) { if (active_watch[i].wd == -1) { active_watch[i].wd = wd; strncpy(active_watch[i].name, name, 64 -1); strncpy(active_watch[i].path, path, WATCH_PATH_LEN -1); strncpy(active_watch[i].parent_name, parent_name, 64 -1); strncpy(active_watch[i].parent_path, parent_path, WATCH_PATH_LEN -1); return; } } DFX_ERR("no room to add more watch"); } struct watch *get_watch(int wd) { int i; for (i = 0; i < MAX_WATCH; i++) { if (active_watch[i].wd == wd) return &active_watch[i]; } return NULL; } char * wd_to_pathname(int wd) { int i; for (i = 0; i < MAX_WATCH; i++) { if (active_watch[i].wd == wd) return active_watch[i].path; } return NULL; } struct watch* path_to_watch(char *path) { int i; for(i=0; i < MAX_WATCH; i++){ if(!strcmp(path,active_watch[i].path)) return &active_watch[i]; } return NULL; } void remove_watch(char *path) { int i; for (i = 0; i < MAX_WATCH; i++) { if (strcmp(active_watch[i].path, path) == 0){ inotify_rm_watch(inotifyFd, active_watch[i].wd); active_watch[i].wd = -1; active_watch[i].path[0] = '\0'; } } } accel_info_t *add_accel_to_base(struct basePLDesign *base, char *name, char *path, char *parent_path) { int j; for (j = 0; j < RP_SLOTS_MAX; j++) { if (!strcmp(base->accel_list[j].path, path)) { DFX_DBG("%s already exists", path); break; } if (base->accel_list[j].path[0] == '\0') { DFX_DBG("adding %s to base %s", path, parent_path); strcpy(base->accel_list[j].name, name); base->accel_list[j].name[sizeof(base->accel_list[j].name) - 1] = '\0'; strcpy(base->accel_list[j].path, path); base->accel_list[j].path[sizeof(base->accel_list[j].path) - 1] = '\0'; strcpy(base->accel_list[j].parent_path, parent_path); base->accel_list[j].parent_path[sizeof(base->accel_list[j].parent_path) - 1] = '\0'; //base->accel_list[j].wd = wd; break; } } return &base->accel_list[j]; } /* * The present limitation is only one level of hierarchy (dir1 and dir2). * In future when we face hierarchical designs that may have RPs within * RMs we will need this scalability. */ void parse_packages(struct basePLDesign *base,char *fname, char *path) { DIR *dir1 = NULL, *dir2 = NULL; struct dirent *d1,*d2; char first_level[512],second_level[800],filename[811]; struct stat stat_info; accel_info_t *accel; int wd; /* For flat shell design there is no subfolder so assign the base path as the accel path */ if (!strcmp(base->type,"XRT_FLAT") || !strcmp(base->type,"PL_FLAT")) { DFX_DBG("%s : %s", base->name, base->type); strcpy(base->accel_list[0].name, base->name); strcpy(base->accel_list[0].path, base->base_path); strcpy(base->accel_list[0].parent_path, base->base_path); strcpy(base->accel_list[0].accel_type, base->type); return; } dir1 = opendir(path); if (dir1 == NULL) { DFX_ERR("Directory %s not found", path); return; } while((d1 = readdir(dir1)) != NULL) { if (d1->d_type == DT_DIR) { if (strlen(d1->d_name) > 64 || strcmp(d1->d_name,".") == 0 || strcmp(d1->d_name,"..") == 0) { continue; } sprintf(first_level,"%s/%s", path, d1->d_name); //add_accel_to_base(dir->d_name, new_dir, path); wd = inotify_add_watch(inotifyFd, first_level, IN_ALL_EVENTS); if (wd == -1){ DFX_ERR("inotify_add_watch failed on %s", first_level); goto close_dir; } add_to_watch(wd, d1->d_name, first_level, fname, path); sprintf(filename,"%s/accel.json",first_level); /* For pl slots we need to traverse next level to find accel.json*/ if (stat(filename,&stat_info)){ dir2 = opendir(first_level); while((d2 = readdir(dir2)) != NULL) { if (d2->d_type == DT_DIR) { if (strlen(d2->d_name) > 64 || strcmp(d2->d_name,".") == 0 || strcmp(d2->d_name,"..") == 0) { continue; } } sprintf(second_level,"%s/%s", first_level, d2->d_name); wd = inotify_add_watch(inotifyFd, second_level, IN_ALL_EVENTS); if (wd == -1){ DFX_ERR("inotify_add_watch failed on %s", second_level); goto close_dir; } add_to_watch(wd, d2->d_name, second_level, d1->d_name, first_level); sprintf(filename,"%s/accel.json",second_level); if (!stat(filename,&stat_info)){ accel = add_accel_to_base(base,d1->d_name, first_level, path); initAccel(accel, second_level); } } } /* Found accel.json so add it*/ else { accel = add_accel_to_base(base,d1->d_name, first_level, path); initAccel(accel, first_level); } } } close_dir: if (dir1) closedir(dir1); if (dir2) closedir(dir2); } void add_base_design(char *name, char *path, char *parent, int wd) { int i; for (i = 0; i < MAX_WATCH; i++) { if (!strcmp(base_designs[i].base_path, path)){ DFX_DBG("Base design %s already exists", path); return; } } // Now find the fist unsued base_designs[] element for (i = 0; i < MAX_WATCH; i++) { if (base_designs[i].base_path[0] == '\0') { DFX_DBG("Adding base design %s", path); strncpy(base_designs[i].name, name, sizeof(base_designs[i].name)-1); base_designs[i].name[sizeof(base_designs[i].name) - 1] = '\0'; strncpy(base_designs[i].base_path, path, sizeof(base_designs[i].base_path)-1); base_designs[i].base_path[sizeof(base_designs[i].base_path) - 1] = '\0'; strncpy(base_designs[i].parent_path, parent, sizeof(base_designs[i].parent_path)-1); base_designs[i].parent_path[sizeof(base_designs[i].parent_path) - 1] = '\0'; base_designs[i].active = 0; base_designs[i].wd = wd; return; } } } void remove_base_design(char *path,char *parent, int is_base) { int i, j; if (!is_base) { DFX_DBG("Removing accel %s from base %s", path, parent); for (i = 0; i < MAX_WATCH; i++) { if (!strcmp(base_designs[i].base_path,parent)) { for (j = 0; j < RP_SLOTS_MAX; j++) { if (!strcmp(base_designs[i].accel_list[j].path,path)) { remove_watch(path); base_designs[i].accel_list[j].name[0] = '\0'; base_designs[i].accel_list[j].path[0] = '\0'; base_designs[i].accel_list[j].parent_path[0] = '\0'; base_designs[i].accel_list[j].wd = -1; break; } } } } return; } for (i = 0; i < MAX_WATCH; i++) { if (strcmp(base_designs[i].base_path, path) == 0) { DFX_DBG("Removing base design %s", path); for (j = 0; j < RP_SLOTS_MAX; j++) { if (base_designs[i].accel_list[j].path[0] != '\0') { remove_watch(path); base_designs[i].accel_list[j].name[0] = '\0'; base_designs[i].accel_list[j].path[0] = '\0'; base_designs[i].accel_list[j].parent_path[0] = '\0'; base_designs[i].accel_list[j].wd = -1; break; } } base_designs[i].name[0] = '\0'; base_designs[i].type[0] = '\0'; base_designs[i].base_path[0] = '\0'; base_designs[i].num_pl_slots = 0; //free(base_designs[i].slots); base_designs[i].active = 0; base_designs[i].wd = -1; return; } } } /*static void displayInotifyEvent(struct inotify_event *i) { printf(" event name = %s\n", i->name); //printf(" wd =%2d; ", i->wd); // if (i->cookie > 0) // printf("cookie =%4d; ", i->cookie); // printf("mask = "); if (i->mask & IN_ACCESS) printf("IN_ACCESS "); if (i->mask & IN_ATTRIB) printf("IN_ATTRIB "); if (i->mask & IN_CLOSE_NOWRITE) printf("IN_CLOSE_NOWRITE "); if (i->mask & IN_CLOSE_WRITE) printf("IN_CLOSE_WRITE "); if (i->mask & IN_CREATE) printf("IN_CREATE "); if (i->mask & IN_DELETE) printf("IN_DELETE "); if (i->mask & IN_DELETE_SELF) printf("IN_DELETE_SELF "); if (i->mask & IN_IGNORED) printf("IN_IGNORED "); if (i->mask & IN_ISDIR) printf("IN_ISDIR "); if (i->mask & IN_MODIFY) printf("IN_MODIFY "); if (i->mask & IN_MOVE_SELF) printf("IN_MOVE_SELF "); if (i->mask & IN_MOVED_FROM) printf("IN_MOVED_FROM "); if (i->mask & IN_MOVED_TO) printf("IN_MOVED_TO "); if (i->mask & IN_OPEN) printf("IN_OPEN "); if (i->mask & IN_Q_OVERFLOW) printf("IN_Q_OVERFLOW "); if (i->mask & IN_UNMOUNT) printf("IN_UNMOUNT "); printf("\n"); // if (i->len > 0){} // printf(" name = %s\n", i->name); }*/ /* * Filter: path a is over 64 char, "." and ".." */ static int d_name_filter(char *a) { return (strlen(a) > 64) || (a[0] == '.' && (a[1] == 0 || (a[1] == '.' && a[2] == 0))); } void acell_dir_add(char *cpath, struct dirent *dirent) { char new_dir[512], fname[600]; char *d_name = dirent->d_name; struct basePLDesign *base; int wd; if (dirent->d_type != DT_DIR || d_name_filter(d_name)) return; sprintf(new_dir, "%s/%s", cpath, d_name); DFX_DBG("Found dir %s", new_dir); wd = inotify_add_watch(inotifyFd, new_dir, IN_ALL_EVENTS); if (wd == -1){ DFX_ERR("inotify_add_watch %s", new_dir); return; } add_to_watch(wd, d_name, new_dir, "", cpath); add_base_design(d_name, new_dir, cpath, wd); base = findBaseDesign(d_name); if (base == NULL) return; sprintf(fname, "%s/shell.json", base->base_path); if (initBaseDesign(base, fname) == 0) parse_packages(base, base->name, base->base_path); } /* * firmware_dir_walk() * For each config.firmware_locations, add a watch for all events */ void firmware_dir_walk(void) { int k, wd; struct dirent *dirent; for(k = 0; k < config.number_locations; k++) { char *fwdir = config.firmware_locations[k]; DIR *d = opendir(fwdir); if (d == NULL) { DFX_ERR("opendir(%s)", fwdir); continue; } if (!path_to_watch(fwdir)) { wd = inotify_add_watch(inotifyFd, fwdir, IN_ALL_EVENTS); if (wd == -1) { DFX_ERR("inotify_add_watch(%s)", fwdir); closedir(d); continue; } add_to_watch(wd, "", fwdir, "", ""); } /* Add packages to inotify */ while ((dirent = readdir(d)) != NULL) acell_dir_add(fwdir, dirent); closedir(d); } } #define BUF_LEN (10 * (sizeof(struct inotify_event) + NAME_MAX + 1)) void *threadFunc(void *) { int wd, j, ret; char buf[BUF_LEN] __attribute__ ((aligned(8))); ssize_t numRead; char *p; char new_dir[512],fname[600]; struct inotify_event *event; struct basePLDesign *base; active_watch = (struct watch *)calloc(sizeof(struct watch), MAX_WATCH); base_designs = (struct basePLDesign *)calloc(sizeof(struct basePLDesign), MAX_WATCH); for(j = 0; j < MAX_WATCH; j++) { active_watch[j].wd = -1; } inotifyFd = inotify_init(); /* Create inotify instance */ if (inotifyFd == -1) DFX_ERR("inotify_init"); firmware_dir_walk(); /* Done parsing on target accelerators, now load a default one if present in config file */ sem_post(&mutex); /* Listen for new updates in firmware path*/ for (;;) { numRead = read(inotifyFd, buf, BUF_LEN); if (numRead <= 0 && errno != EAGAIN) DFX_ERR("read() from inotify failed"); /* Process all of the events in buffer returned by read() */ for (p = buf; p < buf + numRead; ) { event = (struct inotify_event *) p; // displayInotifyEvent(event); if(event->mask & IN_CREATE || event->mask & IN_CLOSE_WRITE){ if (event->mask & IN_ISDIR) { struct watch *w = get_watch(event->wd); if (w == NULL || strstr(event->name, ".dpkg-new")) break; sprintf(new_dir,"%s/%s",w->path, event->name); DFX_DBG("add inotify watch on %s w->name %s parent %s", new_dir, w->name, w->parent_path); wd = inotify_add_watch(inotifyFd, new_dir, IN_ALL_EVENTS); if (wd == -1) DFX_PR("inotify_add_watch failed on %s", new_dir); add_to_watch(wd, event->name, new_dir, w->name,w->path); if (!strcmp(w->parent_path,"")) add_base_design(event->name, new_dir, w->path, wd); } else if(!strcmp(event->name,"shell.json")) { struct watch *w = get_watch(event->wd); if (w == NULL) break; base = findBaseDesign_path(w->path); if (base == NULL) break; sprintf(fname,"%s/%s",w->path,"shell.json"); ret = initBaseDesign(base, fname); if (ret == 0) parse_packages(base,w->name, w->path); } else if(!strcmp(event->name,"accel.json")) { struct watch *w = get_watch(event->wd); struct watch *parent_watch = path_to_watch(w->parent_path); accel_info_t *accel; base = findBaseDesign_path(parent_watch->parent_path); DFX_DBG("Add accel %s to base %s", w->path, base->base_path); accel = add_accel_to_base(base, w->parent_name, w->parent_path, base->base_path); initAccel(accel, w->path); } } else if((event->mask & IN_DELETE) && (event->mask & IN_ISDIR)) { struct watch *w = get_watch(event->wd); if (w == NULL) break; sprintf(new_dir,"%s/%s",w->path, event->name); DFX_DBG("Removing watch on %s parent_path %s", new_dir, w->parent_path); if (!strcmp(w->parent_path,"")) remove_base_design(new_dir, w->path, 1); else remove_base_design(new_dir, w->path, 0); remove_watch(new_dir); } else if((event->mask & IN_MOVED_FROM) && (event->mask & IN_ISDIR)) { struct watch *w = get_watch(event->wd); if (w == NULL) break; sprintf(new_dir,"%s/%s",w->path, event->name); if (!strcmp(w->parent_name,"")) remove_base_design(new_dir, w->path, 1); else remove_base_design(new_dir, w->path, 0); } else if(event->mask & IN_MOVED_TO){ /* * 'dnf install' creates tmp filenames and then does 'mv' to desired filenames. * Hence IN_CREATE notif will be on tmp filenames, add logic in MOVED_TO notification for * shell.json */ if(event->mask & IN_ISDIR || !strcmp(event->name,"shell.json")){ struct watch *w = get_watch(event->wd); if (w == NULL || strstr(event->name, ".dpkg-new")) break; if (event->mask & IN_ISDIR){ sprintf(new_dir,"%s/%s",w->path, event->name); add_base_design(event->name, new_dir, w->path, event->wd); } else { sprintf(new_dir,"%s",w->path); } base = findBaseDesign_path(new_dir); if (base == NULL) break; sprintf(fname,"%s/%s",new_dir,"shell.json"); ret = initBaseDesign(base, fname); if (ret == 0) parse_packages(base,w->name, new_dir); } } p += sizeof(struct inotify_event) + event->len; } } //exit(EXIT_SUCCESS); } int dfx_init() { pthread_t t; strcpy(config.defaul_accel_name, ""); strcpy(platform.boardName,"Xilinx board"); sem_init(&mutex, 0, 0); parse_config(CONFIG_PATH, &config); pthread_create(&t, NULL,threadFunc, NULL); sem_wait(&mutex); //TODO Save active design on filesytem and on reboot read that //if (stat("/configfs/device-tree/overlays",&info)) // ret = system("rmdir /configfs/device-tree/overlays/*"); if (strcmp(config.defaul_accel_name, "") != 0) load_accelerator(config.defaul_accel_name); return 0; } dfx-mgr-xilinx_v2023.2/src/daemon_helper.h000066400000000000000000000016601446677152000205100ustar00rootroot00000000000000/* * Copyright (c) 2021, Xilinx Inc. and Contributors. All rights reserved. * * SPDX-License-Identifier: MIT */ /* * @file daemon_helper.h */ #ifndef _ACAPD_DAEMON_HELPER_H #define _ACAPD_DAEMON_HELPER_H #ifdef __cplusplus extern "C" { #endif #define CONFIG_PATH "/etc/dfx-mgrd/daemon.conf" #define WATCH_PATH_LEN 256 #define MAX_WATCH 500 int load_accelerator(const char *accel_name); int remove_accelerator(int slot); void allocBuffer(uint64_t size); void sendBuff(uint64_t size); void freeBuff(uint64_t pa); int getFD(int slot, char *dev_name); int dfx_getFDs(int slot, int *fd); void list_accel_uio(int, char *, size_t); char *get_accel_uio_by_name(int, const char *); int siha_ir_buf_list(uint32_t sz, char *buf); int siha_ir_buf_set(char *user_slot_seq); void getShellFD(); void getClockFD(); char *listAccelerators(); void getRMInfo(); int dfx_init(); int dfx_getFDs(int slot, int *fd); #ifdef __cplusplus } #endif #endif dfx-mgr-xilinx_v2023.2/src/device.c000066400000000000000000000055051446677152000171420ustar00rootroot00000000000000/* * Copyright (c) 2021, Xilinx Inc. and Contributors. All rights reserved. * * SPDX-License-Identifier: MIT */ #include #include #include #include #include #include #include #include int acapd_device_open(acapd_device_t *dev) { acapd_assert(dev != NULL); return sys_device_open(dev); } int acapd_device_close(acapd_device_t *dev) { acapd_assert(dev != NULL); if (dev->ops != NULL && dev->ops->close != NULL) { return dev->ops->close(dev); } return 0; } void *acapd_device_attach_shm(acapd_device_t *dev, acapd_shm_t *shm) { acapd_list_t *node; void *va; acapd_assert(dev != NULL); acapd_assert(shm != NULL); acapd_list_for_each(&shm->refs, node) { acapd_device_t *tmpdev; tmpdev = (acapd_device_t *)acapd_container_of(node, acapd_device_t, node); if (dev == tmpdev) { /* TODO: in some cases, different device * can map different the same memory differently. */ return shm->va; } } if (dev->ops != NULL && dev->ops->attach != NULL) { va = dev->ops->attach(dev, shm); if (va == NULL) { return NULL; } if (shm->va == NULL) { shm->va = va; } } else { va = shm->va; } acapd_list_add_tail(&shm->refs, &dev->node); shm->refcount++; return va; } int acapd_device_detach_shm(acapd_device_t *dev, acapd_shm_t *shm) { acapd_list_t *node; acapd_assert(dev != NULL); acapd_assert(shm != NULL); acapd_list_for_each(&shm->refs, node) { acapd_device_t *tmpdev; tmpdev = (acapd_device_t *)acapd_container_of(node, acapd_device_t, node); if (tmpdev == dev) { if (dev->ops != NULL && dev->ops->detach != NULL) { int ret; ret = dev->ops->detach(dev, shm); if (ret < 0) { return ret; } } acapd_list_del(&dev->node); shm->refcount--; return 0; } } return -EINVAL; } void *acapd_device_get_reg_va(acapd_device_t *dev) { acapd_assert(dev != NULL); if (dev->va == NULL) { acapd_perror("%s: %s is not opened.\n", __func__, dev->dev_name); } return dev->va; } int acapd_device_get_id(acapd_device_t *dev) { acapd_assert(dev != NULL); return dev->id; } int acapd_device_get(acapd_device_t *dev) { int ret; acapd_assert(dev != NULL); if (dev->priv == NULL) { dev->refs = 0; ret = acapd_device_open(dev); if (ret < 0) { acapd_perror("%s, failed to open %s.\n", __func__, dev->dev_name); return -EINVAL; } } dev->refs++; return 0; } int acapd_device_put(acapd_device_t *dev) { acapd_assert(dev != NULL); if (dev->priv == NULL) { return 0; } if (dev->refs == 0) { return 0; } dev->refs--; if (dev->refs == 0) { /* Close device */ /* TODO: shall we force to close device * if device is not referenced ? */ return acapd_device_close(dev); } return 0; } dfx-mgr-xilinx_v2023.2/src/device.h000066400000000000000000000050151446677152000171430ustar00rootroot00000000000000/* * Copyright (c) 2021, Xilinx Inc. and Contributors. All rights reserved. * * SPDX-License-Identifier: MIT */ /* * @file device.h * @brief device definition. */ #ifndef _ACAPD_DEVICE_H #define _ACAPD_DEVICE_H #ifdef __cplusplus extern "C" { #endif #include #include #include #define ACAPD_ACCEL_STATUS_UNLOADED 0U #define ACAPD_ACCEL_STATUS_LOADING 1U #define ACAPD_ACCEL_STATUS_INUSE 2U #define ACAPD_ACCEL_STATUS_UNLOADING 3U #define ACAPD_ACCEL_SUCCESS 0 #define ACAPD_ACCEL_FAILURE (-1) #define ACAPD_ACCEL_TIMEDOUT (-2) #define ACAPD_ACCEL_MISMATCHED (-3) #define ACAPD_ACCEL_RSCLOCKED (-4) #define ACAPD_ACCEL_NOTSUPPORTED (-5) #define ACAPD_ACCEL_INVALID (-6) #define ACAPD_ACCEL_LOAD_INUSE (-7) #define ACAPD_ACCEL_INPROGRESS 1 #define ACAPD_ACCEL_PKG_TYPE_NONE 0U #define ACAPD_ACCEL_PKG_TYPE_PDI 1U #define ACAPD_ACCEL_PKG_TYPE_LAST 2U typedef struct acapd_device acapd_device_t; typedef struct acapd_shm acapd_shm_t; typedef struct acapd_device_ops { int (*open)(acapd_device_t *dev); int (*close)(acapd_device_t *dev); void *(*attach)(acapd_device_t *dev, acapd_shm_t *shm); int (*detach)(acapd_device_t *dev, acapd_shm_t *shm); uint64_t (*va_to_da)(acapd_device_t *dev, void *va); } acapd_device_ops_t; typedef struct acapd_device { char *dev_name; /**< device name */ char *bus_name; /**< bus name */ char path[64]; /**< file path */ uint64_t reg_pa; /**< physical base address */ size_t reg_size; /**< size of the registers */ int id; /**< device id. In Linux, it can be file id */ int intr_id; /**< interrupt id */ void *va; /**< logical address */ char *version; /**< device version */ char *driver; /**< name of the driver */ int iommu_group; /**< iommu group */ int refs; /**< references to this device */ int dma_hls_fd; acapd_device_ops_t *ops; /**< device operation */ void *priv; /**< device private information */ acapd_list_t node; /**< node to link to shm reference list */ } acapd_device_t; int acapd_device_open(acapd_device_t *dev); int acapd_device_close(acapd_device_t *dev); int acapd_device_get(acapd_device_t *dev); int acapd_device_put(acapd_device_t *dev); void *acapd_device_attach_shm(acapd_device_t *dev, acapd_shm_t *shm); int acapd_device_detach_shm(acapd_device_t *dev, acapd_shm_t *shm); void *acapd_device_get_reg_va(acapd_device_t *dev); int acapd_device_get_id(acapd_device_t *dev); #ifdef ACAPD_INTERNAL int sys_device_open(acapd_device_t *dev); #endif /* ACAPD_INTERNAL */ #ifdef __cplusplus } #endif #endif /* _ACAPD_DEVICE_H */ dfx-mgr-xilinx_v2023.2/src/dfx-mgr.service000066400000000000000000000007401446677152000204610ustar00rootroot00000000000000# SPDX-License-Identifier: MIT # # DFX manager daemon is used to demonstrate Dynamic Function eXchange (DFX) # or partial reconfiguration feature on Xilinx Zynq UltraScale+ and newer. # See: UG909 "Vivado Design Suite User Guide Dynamic Function eXchange" [Unit] Description=dfx-mgrd Dynamic Function eXchange Documentation=https://github.com/Xilinx/dfx-mgr [Service] ExecStartPre=-/usr/bin/xlnx-firmware-detect ExecStart=/usr/bin/dfx-mgrd [Install] WantedBy=multi-user.target dfx-mgr-xilinx_v2023.2/src/dfx-mgr.sh000066400000000000000000000000401446677152000174240ustar00rootroot00000000000000#! /bin/sh /usr/bin/dfx-mgrd & dfx-mgr-xilinx_v2023.2/src/dfxmgr_client.c000066400000000000000000000317661446677152000205400ustar00rootroot00000000000000/* * Copyright (c) 2021, Xilinx Inc. and Contributors. All rights reserved. * * SPDX-License-Identifier: MIT */ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "dfxmgr_client.h" #define MAX_FD 25 struct message message; int sock_fd; #if 0 #include static int interrupted; static struct lws *web_socket; static const char *arg; static const char *cmd; struct pss { char body_part; }; struct msg{ char cmd[32]; char arg[32]; }; struct resp{ char data[128]; int len; }; struct resp *response; static int msgs_sent; #define EXAMPLE_RX_BUFFER_BYTES (sizeof(struct resp)) struct payload { unsigned char data[LWS_SEND_BUFFER_PRE_PADDING + EXAMPLE_RX_BUFFER_BYTES + LWS_SEND_BUFFER_POST_PADDING]; size_t len; } received_payload; static int callback_example( struct lws *wsi, enum lws_callback_reasons reason, void *user, void *in, size_t len ) { struct msg *m; //struct resp *r; switch( reason ) { case LWS_CALLBACK_CLIENT_ESTABLISHED: printf("LWS_CALLBACK_CLIENT_ESTABLISHED user %s\n",(char *)user); lws_callback_on_writable( wsi ); break; case LWS_CALLBACK_CLIENT_RECEIVE: msgs_sent--; printf("LWS_CALLBACK_CLIENT_RECEIVE count %d\n",msgs_sent); memcpy( &received_payload.data[LWS_SEND_BUFFER_PRE_PADDING], in, len ); received_payload.len = len; response = (struct resp *)&received_payload.data[LWS_SEND_BUFFER_PRE_PADDING]; printf("client recieved data %s len %d\n",response->data,response->len); if(!msgs_sent) interrupted = 1; break; case LWS_CALLBACK_CLIENT_WRITEABLE: printf("LWS_CALLBACK_CLIENT_WRITEABLE count %d\n",msgs_sent); unsigned char buf[LWS_SEND_BUFFER_PRE_PADDING + sizeof(struct msg) + LWS_SEND_BUFFER_POST_PADDING]; //unsigned char *p = &buf[LWS_SEND_BUFFER_PRE_PADDING]; //size_t n = sprintf( (char *)p, "%u", rand() ); m = (struct msg *)&buf[LWS_SEND_BUFFER_PRE_PADDING]; sprintf(m->cmd,"%s",cmd); sprintf(m->arg,"%s",arg); acapd_perror("client writing cmd %s arg %s\n",m->cmd,m->arg); lws_write( wsi, (unsigned char *)m, sizeof(struct msg), LWS_WRITE_TEXT ); if(strcmp(cmd,"-loadpdi")){ //sleep(2); interrupted = 1; }else { //sleep(1); msgs_sent++; } acapd_perror("LWS_CALLBACK_CLIENT_WRITEABLE done count %d\n",msgs_sent); break; case LWS_CALLBACK_CLOSED: printf("LWS_CALLBACK_CLOSED\n"); interrupted = 1; break; case LWS_CALLBACK_CLIENT_CONNECTION_ERROR: lwsl_user("CLIENT_CONNECTION_ERROR: %s\n", in ? (char *)in : "(null)"); interrupted = 1; break; default: break; } return lws_callback_http_dummy(wsi, reason, user, in, len); } static struct lws_protocols protocols[] = { { "example-protocol", callback_example, 0, EXAMPLE_RX_BUFFER_BYTES, 0, NULL, 0 }, { NULL, NULL, 0, 0, 0, NULL, 0} // terminator }; static void sigint_handler(int sig) { printf("Recieved signal %d\n",sig); interrupted = 1; } int exchangeCommand(char* path, char* argvalue){ struct lws_context_creation_info info; struct lws_context *context; struct lws_client_connect_info ccinfo = {0}; signal(SIGINT, sigint_handler); memset(&info, 0, sizeof info); memset(&ccinfo, 0, sizeof ccinfo); interrupted = 0; info.port = CONTEXT_PORT_NO_LISTEN; info.protocols = protocols; info.gid = -1; info.uid = -1; //info.connect_timeout_secs = 30; context = lws_create_context(&info); if (!context) { lwsl_err("lws init failed\n"); return 1; } ccinfo.context = context; ccinfo.address = "localhost"; ccinfo.port = 7681; ccinfo.protocol = protocols[0].name; ccinfo.path = "/"; cmd = path; arg = argvalue; //ccinfo.ssl_connection = LCCSCF_HTTP_MULTIPART_MIME | LCCSCF_ALLOW_SELFSIGNED; //ccinfo.method = "POST"; web_socket = lws_client_connect_via_info(&ccinfo); lwsl_user("WS client started\n"); while (!interrupted){ //printf("starting lws_service client\n"); if(lws_service(context, 15)) interrupted = 1; } lws_context_destroy(context); return 0; } #endif /* 0 */ int dfxmgr_load(char* pkg_name) { struct message send_msg, recv_msg; socket_t gs; if (pkg_name == NULL || pkg_name[0] == 0) { DFX_ERR("need package name"); return -1; } initSocket(&gs); send_msg.id = LOAD_ACCEL; send_msg.size = strlen(pkg_name); strncpy(send_msg.data, pkg_name, sizeof(send_msg.data)); if (write(gs.sock_fd, &send_msg, HEADERSIZE + send_msg.size) < 0) { DFX_ERR("write(%d)", gs.sock_fd); return -1; } if (read(gs.sock_fd, &recv_msg, sizeof(struct message)) < 0) { DFX_ERR("No message or read(%d) error", gs.sock_fd); return -1; } DFX_PR("Accelerator %s loaded to slot %s", pkg_name, recv_msg.data); return atoi(recv_msg.data); } int dfxmgr_remove(int slot) { struct message send_msg, recv_msg; socket_t gs; if (slot < 0){ DFX_ERR("invalid slot %d", slot); return -1; } initSocket(&gs); send_msg.id = REMOVE_ACCEL; send_msg.size = 2; sprintf(send_msg.data, "%d", slot); if (write(gs.sock_fd, &send_msg, HEADERSIZE + send_msg.size) < 0) { DFX_ERR("write(%d)", gs.sock_fd); return -1; } if (read(gs.sock_fd, &recv_msg, sizeof (struct message)) < 0) { DFX_ERR("No message or read(%d) error", gs.sock_fd); return -1; } DFX_PR("remove from slot %d returns: %s (%s)", slot, recv_msg.data, recv_msg.data[0] == '0' ? "Ok" : "Error"); return recv_msg.data[0] == '0' ? 0 : -1; } /* * We expect a short path in the recv_msg.data, e.g.: /dev/uioN, * and we will copy at most NAME_MAX characters via strncpy. * However, the compiler flags -Wall -Werror -Wextra force * "output may be truncated copying .." error for strncpy. * Add __attribute__((nonstring)) to avoid the error message. */ char * dfxmgr_uio_by_name(char *obuf __attribute__((nonstring)), int slot, const char *name) { struct message send_msg, recv_msg; socket_t gs; if (slot < 0 || !name || name[0] == 0) { DFX_ERR("invalid slot %d, or no name", slot); return NULL; } initSocket(&gs); send_msg.id = LIST_ACCEL_UIO; send_msg._u.slot = slot; send_msg.size = 1 + strlen(name); strncpy(send_msg.data, name, sizeof(send_msg.data)); if (write(gs.sock_fd, &send_msg, HEADERSIZE + send_msg.size) < 0) { DFX_ERR("write(%d)", gs.sock_fd); return NULL; } if (read(gs.sock_fd, &recv_msg, sizeof(struct message)) < 0) { DFX_ERR("No message or read(%d) error", gs.sock_fd); return NULL; } strncpy(obuf, recv_msg.data, NAME_MAX); return obuf; } /** * dfxmgr_siha_ir_buf_set - Set up Inter-RM buffers for I/O between slots * @sz: the number of elements in slot_seq array * @slot_seq: array of slot IDs to connect * * In 2RP design there are only two possible slot_seq: * {0, 1} slot 0 writes to IR-buf 1; slot 1 reads from its IR-buf * {1, 0} slot 1 writes to IR-buf 0; slot 0 reads from its IR-buf * In 3RP design there are 12 sets, 6 w/ two slots and 6 w/ 3 slots. * E.g.: {1, 2, 0} * slot 1 writes to IR-buf 2, * slot 2 reads from its IR-buf 2 and writes to IR-buf 0, * slot 0 reads from its IR-buf 0 * * Returns: 0 if connected successfully; non-0 otherwise */ int dfxmgr_siha_ir_buf_set(const char *user_slot_seq) { struct message send_msg, recv_msg; socket_t gs; if (!user_slot_seq) { DFX_ERR("user_slot_seq is 0"); return -1; } initSocket(&gs); send_msg.id = SIHA_IR_SET; send_msg.size = 1 + strlen(user_slot_seq); strncpy(send_msg.data, user_slot_seq, sizeof(send_msg.data)); if (write(gs.sock_fd, &send_msg, HEADERSIZE + send_msg.size) < 0) { DFX_ERR("write(%d)", gs.sock_fd); return -1; } if (read(gs.sock_fd, &recv_msg, sizeof(struct message)) < 0) { DFX_ERR("No message or read(%d) error", gs.sock_fd); return -1; } DFX_PR("SIHA_IR_SET (%s) returns: %s", user_slot_seq, recv_msg.data[0] == '0' ? "Ok" : "Error"); return recv_msg.data[0] == '0' ? 0 : -1; } /** * dfxmgr_siha_ir_list - list DMs configuration, see siha_ir_buf_list * @sz: the size of the buf * @buf: buffer to put the DMs configuration * * Returns: pointer to the buffer obuf */ char * dfxmgr_siha_ir_list(uint32_t sz, char *obuf) { struct message send_msg, recv_msg; socket_t gs; if (!obuf) { DFX_ERR("obuf is 0"); return NULL; } initSocket(&gs); send_msg.id = SIHA_IR_LIST; send_msg.size = 0; if (write(gs.sock_fd, &send_msg, HEADERSIZE + send_msg.size) < 0) { DFX_ERR("write(%d)", gs.sock_fd); return NULL; } if (read(gs.sock_fd, &recv_msg, sizeof(struct message)) < 0) { DFX_ERR("No message or read(%d) error", gs.sock_fd); return NULL; } strncpy(obuf, recv_msg.data, sz); return obuf; } ssize_t sock_fd_write(int sock, void *buf, ssize_t buflen, int *fd, int fdcount) { ssize_t size; struct msghdr msg; struct iovec iov; union { struct cmsghdr cmsghdr; char control[CMSG_SPACE(sizeof (int) * MAX_FD)]; } cmsgu; struct cmsghdr *cmsg; iov.iov_base = buf; iov.iov_len = buflen; msg.msg_name = NULL; msg.msg_namelen = 0; msg.msg_iov = &iov; msg.msg_iovlen = 1; msg.msg_flags = 0; if (fd[0] != -1) { msg.msg_control = cmsgu.control; msg.msg_controllen = sizeof(cmsgu.control); cmsg = CMSG_FIRSTHDR(&msg); cmsg->cmsg_len = CMSG_LEN(MAX_FD * sizeof (int)); cmsg->cmsg_level = SOL_SOCKET; cmsg->cmsg_type = SCM_RIGHTS; memset(CMSG_DATA(cmsg), '\0', MAX_FD * sizeof(int)); memcpy(CMSG_DATA(cmsg), fd, fdcount * sizeof(int)); } else { msg.msg_control = NULL; msg.msg_controllen = 0; } size = sendmsg(sock, &msg, 0); if (size < 0) acapd_perror("%s:sendmsg() failed\n",__func__); return size; } ssize_t sock_fd_read(int sock, struct message *buf, int *fd, int *fdcount) { ssize_t size = 0; struct msghdr msg; struct iovec iov; union { struct cmsghdr cmsghdr; char control[CMSG_SPACE(sizeof (int) * MAX_FD)]; } cmsgu; struct cmsghdr *cmsg; iov.iov_base = buf; iov.iov_len = 1024*4; msg.msg_name = NULL; msg.msg_namelen = 0; msg.msg_iov = &iov; msg.msg_iovlen = 1; msg.msg_flags = 0; msg.msg_control = cmsgu.control; msg.msg_controllen = sizeof(cmsgu.control); size = recvmsg (sock, &msg, 0); if (size < 0) { acapd_perror("%s:recvmsg() failed\n",__func__); exit(1); } *fdcount = buf->_u.fdcount; cmsg = CMSG_FIRSTHDR(&msg); if (cmsg && cmsg->cmsg_len == CMSG_LEN(sizeof(int))) { if (cmsg->cmsg_level != SOL_SOCKET) { acapd_perror("%s: invalid cmsg_level %d\n",__func__, cmsg->cmsg_level); exit(1); } if (cmsg->cmsg_type != SCM_RIGHTS) { acapd_perror("%s: invalid cmsg_type %d\n",__func__, cmsg->cmsg_type); exit(1); } } memcpy(fd, CMSG_DATA(cmsg), sizeof(int)*(*fdcount)); return size; } int initSocket(socket_t* gs) { const struct sockaddr_un su = { .sun_family = AF_UNIX, .sun_path = SERVER_SOCKET, }; if ((gs->sock_fd = socket(AF_UNIX, SOCK_SEQPACKET, 0)) == -1){ DFX_ERR("socket(AF_UNIX, SOCK_SEQPACKET, 0)"); return -1; } gs->socket_address = su; if (connect(gs->sock_fd, (const struct sockaddr *)&su, sizeof(su)) < 0){ DFX_ERR("connect(%s)", SERVER_SOCKET); return -1; } return 0; } int graphClientSubmit(socket_t *gs, char* json, int size, int *fd, int *fdcount){ struct message send_message, recv_message; int ret; memset(&send_message, '\0', sizeof(struct message)); send_message.id = GRAPH_INIT; send_message.size = size; send_message._u.fdcount = 0; memcpy(send_message.data, json, size); ret = write(gs->sock_fd, &send_message, HEADERSIZE + send_message.size); if (ret < 0){ acapd_perror("%s:graphClientSubmit write() failed\n",__func__); return -1; } memset(&recv_message, '\0', sizeof(struct message)); size = sock_fd_read(gs->sock_fd, &recv_message, fd, fdcount); if (size <= 0) return -1; return 0; } int graphClientFinalise(socket_t *gs, char* json, int size){ struct message send_message, recv_message; int ret; memset(&send_message, '\0', sizeof(struct message)); send_message.id = GRAPH_FINALISE; send_message.size = size; send_message._u.fdcount = 0; memcpy(send_message.data, json, size); ret = write(gs->sock_fd, &send_message, HEADERSIZE + send_message.size); if (ret < 0){ acapd_perror("%s:graphClientFinalise write() failed\n",__func__); return -1; } memset(&recv_message, '\0', sizeof(struct message)); size = read(gs->sock_fd, &recv_message, sizeof (struct message)); if (size <= 0) return -1; return 0; } dfx-mgr-xilinx_v2023.2/src/dfxmgr_client.h000066400000000000000000000042451446677152000205350ustar00rootroot00000000000000/* * Copyright (c) 2021, Xilinx Inc. and Contributors. All rights reserved. * * SPDX-License-Identifier: MIT */ #ifndef _ACAPD_SOCKET_H #define _ACAPD_SOCKET_H #ifdef __cplusplus extern "C" { #endif #include #include #include #define SERVER_SOCKET "/tmp/dfx-mgrd.socket" #define MAX_MESSAGE_SIZE 4*1024 #define BACKLOG 10 enum dfx_mgr_request { DFX_MGR_REQ_FIRST, QUIT = DFX_MGR_REQ_FIRST, GRAPH_INIT, GRAPH_FINALISE, GRAPH_STAGED, GRAPH_GET_IOBUFF, GRAPH_SET_IOBUFF, LOAD_ACCEL, REMOVE_ACCEL, LIST_PACKAGE, LIST_ACCEL_UIO, DFX_MGR_REQ_10, /* unused */ GRAPH_INIT_DONE, GRAPH_FINALISE_DONE, GRAPH_STAGED_DONE, SIHA_IR_LIST, SIHA_IR_SET, }; #define MAX_CLIENTS 200 #define HEADERSIZE 24 struct message { uint32_t id; uint32_t size; union { uint32_t fdcount; uint32_t slot; } _u; char data [32*1024]; }; extern void error (char *msg); typedef struct { int sock_fd; struct sockaddr_un socket_address; } socket_t; extern int initSocket(socket_t *gs); extern int graphClientSubmit(socket_t *gs, char* json, int size, int *fd, int *fdcount); extern int graphClientFinalise(socket_t *gs, char* json, int size); extern ssize_t sock_fd_write(int sock, void *buf, ssize_t buflen, int *fd, int fdcount); extern ssize_t sock_fd_read(int sock, struct message *buf, int *fd, int *fdcount); typedef struct fds{ int s2mm_fd; int mm2s_fd; int config_fd; int accelconfig_fd; int dma_hls_fd; uint64_t mm2s_pa; uint64_t mm2s_size; uint64_t s2mm_pa; uint64_t s2mm_size; uint64_t config_pa; uint64_t config_size; } fds_t; extern int dfxmgr_load(char* packageName); extern int dfxmgr_remove(int slot); extern char *dfxmgr_uio_by_name(char *obuf, int slot, const char *name); extern char *dfxmgr_siha_ir_list(uint32_t sz, char *obuf); extern int dfxmgr_siha_ir_buf_set(const char *user_slot_seq); //extern int getFD(char* argvalue); //extern int getPA(char* argvalue); //extern int getShellFD(); //extern int getClockFD(); //extern int socketGetFd(int slot, fds_t *fds); //extern int socketGetPA(int slot, fds_t *fds); //extern int test(); #ifdef __cplusplus } #endif #endif dfx-mgr-xilinx_v2023.2/src/dma.c000066400000000000000000000120071446677152000164370ustar00rootroot00000000000000/* * Copyright (c) 2021, Xilinx Inc. and Contributors. All rights reserved. * * SPDX-License-Identifier: MIT */ #include #include #include #include #include #include #include void *acapd_dma_attach(acapd_chnl_t *chnl, acapd_shm_t *shm) { if (chnl == NULL) { acapd_perror("%s: channel pointer is NULL.\n", __func__); return NULL; } if (shm == NULL) { acapd_perror("%s: shm is NULL.\n", __func__); return NULL; } acapd_assert(chnl->dev != NULL); return acapd_device_attach_shm(chnl->dev, shm); } int acapd_dma_detach(acapd_chnl_t *chnl, acapd_shm_t *shm) { if (chnl == NULL) { acapd_perror("%s: channel pointer is NULL.\n", __func__); return -EINVAL; } if (shm == NULL) { acapd_perror("%s: shm is NULL.\n", __func__); return -EINVAL; } acapd_assert(chnl->dev != NULL); return acapd_device_detach_shm(chnl->dev, shm); } int acapd_dma_transfer(acapd_chnl_t *chnl, acapd_dma_config_t *config) { acapd_shm_t *shm; void *va; size_t size; if (chnl == NULL) { acapd_perror("%s: channel pointer is NULL.\n", __func__); return -EINVAL; } if (chnl->ops == NULL) { acapd_perror("%s: channel ops is NULL.\n", __func__); return -EINVAL; } if (chnl->ops->transfer == NULL) { acapd_perror("%s: channel config dma op is NULL.\n", __func__); return -EINVAL; } if (config == NULL) { acapd_perror("%s: channel config is NULL.\n", __func__); return -EINVAL; } if (config->shm == NULL) { acapd_perror("%s: channel config shm is NULL.\n", __func__); return -EINVAL; } va = config->va; size = config->size; shm = config->shm; acapd_debug("%s: =>%p, =>%p \n", __func__, va, shm->va); if ((char *)va < (char *)shm->va || (char *)va + size > (char *)shm->va + shm->size) { acapd_perror("%s: %p,size 0x%llx is beyond %p,size 0x%llx.\n", __func__, va, size, shm->va, shm->size); return -EINVAL; } return chnl->ops->transfer(chnl, config); } int acapd_dma_stop(acapd_chnl_t *chnl) { if (chnl == NULL) { acapd_perror("%s: channel pointer is NULL.\n", __func__); return -EINVAL; } if (chnl->ops == NULL) { acapd_perror("%s: channel ops is NULL.\n", __func__); return -EINVAL; } if (chnl->ops->stop == NULL) { acapd_perror("%s: channel stop dma op is NULL.\n", __func__); return -EINVAL; } return chnl->ops->stop(chnl); } int acapd_dma_poll(acapd_chnl_t *chnl, uint32_t wait_for_complete, acapd_dma_cb_t cb, uint32_t timeout) { acapd_chnl_status_t status; /* TODO: timeout and async */ (void)cb; (void)timeout; if (chnl == NULL) { acapd_perror("%s: channel pointer is NULL.\n", __func__); return -EINVAL; } if (chnl->ops == NULL) { acapd_perror("%s: channel ops is NULL.\n", __func__); return -EINVAL; } if (chnl->ops->poll == NULL) { acapd_perror("%s: channel poll dma op is NULL.\n", __func__); return -EINVAL; } do { status = chnl->ops->poll(chnl); if (status == ACAPD_CHNL_ERRORS) { return (int)(-status); } else if (status == ACAPD_CHNL_IDLE) { return 0; } else if (status == ACAPD_CHNL_STALLED) { return ACAPD_CHNL_STALLED; } }while(wait_for_complete); return (int)ACAPD_CHNL_INPROGRESS; } int acapd_dma_reset(acapd_chnl_t *chnl) { if (chnl == NULL) { acapd_perror("%s: channel pointer is NULL.\n", __func__); return -EINVAL; } if (chnl->ops == NULL) { acapd_perror("%s: channel ops is NULL.\n", __func__); return -EINVAL; } if (chnl->ops->reset == NULL) { acapd_perror("%s: channel reset dma op is NULL.\n", __func__); return -EINVAL; } return chnl->ops->reset(chnl); } int acapd_dma_open(acapd_chnl_t *chnl) { int ret; acapd_debug("%s\n", __func__); if (chnl == NULL) { acapd_perror("%s: channel pointer is NULL.\n", __func__); return -EINVAL; } if (chnl->is_open != 0) { return 0; } if (chnl->ops == NULL || chnl->ops->open == NULL) { acapd_perror("%s: no open channel ops.\n", __func__); return -EINVAL; } ret = chnl->ops->open(chnl); if (ret != 0) { acapd_perror("%s: system failed to open DMA channel.\n", __func__); return -EINVAL; } chnl->is_open = 1; return 0; } int acapd_dma_close(acapd_chnl_t *chnl) { acapd_debug("%s\n", __func__); if (chnl->is_open == 0) { return 0; } chnl->is_open = 0; if (chnl->ops == NULL) { return 0; } if (chnl->ops->close == NULL) { return 0; } return chnl->ops->close(chnl); } int acapd_create_dma_channel(const char *name, acapd_device_t *dev, acapd_chnl_conn_t conn_type, int chnl_id, acapd_dir_t dir, acapd_chnl_t *chnl) { if (chnl == NULL) { acapd_perror("%s: channel pointer is NULL.\n", __func__); return -EINVAL; } if (dev == NULL) { acapd_perror("%s: dev pointer is NULL.\n", __func__); return -EINVAL; } chnl->dev = dev; chnl->chnl_id = chnl_id; chnl->dir = dir; chnl->conn_type = conn_type; chnl->name = name; return acapd_dma_open(chnl); } int acapd_destroy_dma_channel(acapd_chnl_t *chnl) { if (chnl == NULL) { acapd_perror("%s: channel pointer is NULL.\n", __func__); return -EINVAL; } return acapd_dma_close(chnl); } dfx-mgr-xilinx_v2023.2/src/dma.h000066400000000000000000000105161446677152000164470ustar00rootroot00000000000000/* * Copyright (c) 2021, Xilinx Inc. and Contributors. All rights reserved. * * SPDX-License-Identifier: MIT */ /* * @file dma.h * @brief DMA primitives */ #ifndef _ACAPD_DMA_H #define _ACAPD_DMA_H #ifdef __cplusplus extern "C" { #endif #include #include #include #include #include /** \defgroup dma DMA Interfaces * @{ */ /** * @brief ACAPD DMA transaction direction */ typedef enum acapd_dir { ACAPD_DMA_DEV_R = 1U, /**< DMA direction, device read */ ACAPD_DMA_DEV_W, /**< DMA direction, device write */ ACAPD_DMA_DEV_RW, /**< DMA direction, device read/write */ } acapd_dir_t; /** * @brief ACAPD channel connection type */ typedef enum acapd_chnl_conn { ACAPD_CHNL_CC = 0x1U, /**< Connection is cache coherent */ ACAPD_CHNL_NONC = 0x2U, /**< Connection is not cache coherent */ ACAPD_CHNL_VADDR = 0x4U, /**< Connection is not cache coherent */ } acapd_chnl_conn_t; /** * @brief ACAPD channel status */ typedef enum acpad_chnl_status { ACAPD_CHNL_IDLE = 0U, /**< Channel is idle */ ACAPD_CHNL_INPROGRESS = 1U, /**< Channel is in progress */ ACAPD_CHNL_STALLED = 2U, /**< Channel is stalled */ ACAPD_CHNL_ERRORS = 4U, /**< Channel is stalled */ ACAPD_CHNL_TIMEOUT = 8U, /**< Channel is stalled */ } acapd_chnl_status_t; #define ACAPD_MAX_DIMS 4U /** * @brief ACAPD data shape structure */ typedef struct acapd_shape { int num_of_dims; /**< Number of dimensions */ int dim[ACAPD_MAX_DIMS]; /**< Number of elements in each dimension */ } acapd_shape_t; typedef struct acapd_chnl acapd_chnl_t; typedef struct acapd_shm acapd_shm_t; /** * @brief DMA fence data structure * TODO */ typedef int acapd_fence_t; /** * @brief DMA poll callback * TODO */ typedef void (*acapd_dma_cb_t)(acapd_chnl_t *chnl, int reason); /** * @brief DMA configuration type */ typedef struct acapd_dma_config { acapd_shm_t *shm; /**< shared memory pointer */ void *va; /**< start address of the data in the shared memory */ size_t size; /**< size of the data */ acapd_shape_t *stride; /**< stride in the data transfer */ uint32_t auto_repeat; /**< if the dma transfer will auto repeat */ acapd_fence_t *fence; /**< fence of the dma transfer */ uint8_t tid; /* tid is 8bits in bd*/ } acapd_dma_config_t; /** DMA Channel Operations */ typedef struct acapd_dma_ops { const char name[128]; /**< name of the DMA operation */ int (*open)(acapd_chnl_t *chnl); int (*close)(acapd_chnl_t *chnl); int (*transfer)(acapd_chnl_t *chnl, acapd_dma_config_t *config); int (*stop)(acapd_chnl_t *chnl); acapd_chnl_status_t (*poll)(acapd_chnl_t *chnl); int (*reset)(acapd_chnl_t *chnl); } acapd_dma_ops_t; /** * @brief ACAPD DMA channel data structure */ typedef struct acapd_chnl { const char *name; /**< DMA channel name/or path */ acapd_device_t *dev; /**< pointer to the DMA device */ int chnl_id; /**< hardware channel id of a data mover controller */ acapd_dir_t dir; /**< DMA channel direction */ uint32_t conn_type; /**< type of data connection with this channel */ void *sys_info; /**< System private data for the channel */ int is_open; /**< Indicate if the channel is open */ acapd_dma_ops_t *ops; /**< DMA operations */ acapd_list_t node; /**< list node */ char *bd_va; uint32_t max_buf_size; } acapd_chnl_t; static inline void acapd_dma_init_config(acapd_dma_config_t *config, acapd_shm_t *shm, void *va, size_t size, uint8_t tid) { config->shm = shm; config->va = va; config->size = size; config->auto_repeat = 0; config->stride = NULL; config->fence = NULL; config->tid = tid; } void *acapd_dma_attach(acapd_chnl_t *chnl, acapd_shm_t *shm); int acapd_dma_detach(acapd_chnl_t *chnl, acapd_shm_t *shm); int acapd_dma_transfer(acapd_chnl_t *chnl, acapd_dma_config_t *config); int acapd_dma_stop(acapd_chnl_t *chnl); int acapd_dma_poll(acapd_chnl_t *chnl, uint32_t wait_for_complete, acapd_dma_cb_t poll_cb, uint32_t timeout); int acapd_dma_open(acapd_chnl_t *chnl); int acapd_dma_reset(acapd_chnl_t *chnl); int acapd_dma_close(acapd_chnl_t *chnl); int acapd_create_dma_channel(const char *name, acapd_device_t *dev, acapd_chnl_conn_t conn_type, int chnl_id, acapd_dir_t dir, acapd_chnl_t *chnl); int acapd_destroy_dma_channel(acapd_chnl_t *chnl); #include /** @} */ #ifdef __cplusplus } #endif #endif /* _ACAPD_DMA_H */ dfx-mgr-xilinx_v2023.2/src/helper.h000066400000000000000000000045171446677152000171710ustar00rootroot00000000000000/* * Copyright (c) 2021, Xilinx Inc. and Contributors. All rights reserved. * * SPDX-License-Identifier: MIT */ /* * @file helper.h * @brief helper types functions definition. */ #ifndef _ACAPD_HELPER_H #define _ACAPD_HELPER_H #ifdef __cplusplus extern "C" { #endif #include typedef struct acapd_list { struct acapd_list *next, *prev; }acapd_list_t; #define ACAPD_INIT_LIST(name) { .next = &name, .prev = &name } #define ACAPD_DECLARE_LIST(name) \ acapd_list_t name = ACAPD_INIT_LIST(name) static inline void acapd_list_init(acapd_list_t *list) { list->next = list->prev = list; } static inline void acapd_list_add_before(acapd_list_t *node, acapd_list_t *new_node) { new_node->prev = node->prev; new_node->next = node; new_node->next->prev = new_node; new_node->prev->next = new_node; } static inline void acapd_list_add_after(acapd_list_t *node, acapd_list_t *new_node) { new_node->prev = node; new_node->next = node->next; new_node->next->prev = new_node; new_node->prev->next = new_node; } static inline void acapd_list_add_head(acapd_list_t *list, acapd_list_t *node) { acapd_list_add_after(list, node); } static inline void acapd_list_add_tail(acapd_list_t *list, acapd_list_t *node) { acapd_list_add_before(list, node); } static inline int acapd_list_is_empty(acapd_list_t *list) { return list->next == list; } static inline void acapd_list_del(acapd_list_t *node) { node->next->prev = node->prev; node->prev->next = node->next; node->next = node->prev = node; } static inline acapd_list_t *acapd_list_first(acapd_list_t *list) { return acapd_list_is_empty(list) ? NULL : list->next; } #define acapd_list_for_each(list, node) \ for ((node) = (list)->next; \ (node) != (list); \ (node) = (node)->next) #define offset_of(structure, member) \ ((uintptr_t)&(((structure *)0)->member)) #define acapd_container_of(ptr, structure, member) \ (void *)((uintptr_t)(ptr) - offset_of(structure, member)) /** Align 'size' down to a multiple of 'align' (must be a power of two). */ #define acapd_align_down(size, align) \ ((size) & ~((align) - 1)) /** Align 'size' up to a multiple of 'align' (must be a power of two). */ #define acapd_align_up(size, align) \ acapd_align_down((size) + (align) - 1, align) #ifdef __cplusplus } #endif #endif /* _ACAPD_HELPER_H */ dfx-mgr-xilinx_v2023.2/src/json-config.h000066400000000000000000000013111446677152000201130ustar00rootroot00000000000000/* * Copyright (c) 2021, Xilinx Inc. and Contributors. All rights reserved. * * SPDX-License-Identifier: MIT */ /* * @file linux/json-config.h * @brief Linux specific Json config definition. */ #ifndef _ACAPD_LINUX_JSON_CONFIG_H #define _ACAPD_LINUX_JSON_CONFIG_H #include #include #include int parseAccelJson(acapd_accel_t *accel, char *filename); int parseShellJson(acapd_shell_t *shell, const char *filename); int initBaseDesign(struct basePLDesign *base, const char *shell_path); void parse_config(char *config_path, struct daemon_config *config); int initAccel(accel_info_t *accel, const char *path); #endif /* _ACAPD_LINUX_JSON_CONFIG_H */ dfx-mgr-xilinx_v2023.2/src/model.h000066400000000000000000000026001446677152000170010ustar00rootroot00000000000000/* * Copyright (c) 2021, Xilinx Inc. and Contributors. All rights reserved. * * SPDX-License-Identifier: MIT */ /* * @file model.h * @brief runtime data model. */ #ifndef _ACAPD_MODEL_H #define _ACAPD_MODEL_H #ifdef __cplusplus extern "C" { #endif #define MAX_PATH_SIZE 512 #define RP_SLOTS_MAX 10 #define ARRAY_SIZE(a) (sizeof(a)/sizeof((a)[0])) typedef struct { char name[64]; char path[512]; int uid; int parent_uid; /**< future: 2+ deep hierarchal reconfiguration */ int is_aie; acapd_accel_t *accel; // This tracks active PL dfx in this slot }slot_info_t; typedef struct { int uid; int pid; /**< parent's UID should match shell's UID */ char name[64]; char path[512]; char parent_name[64]; char parent_path[512]; int wd; char accel_type[32]; }accel_info_t; struct basePLDesign { int uid; int fpga_cfg_id; char name[64]; char base_path[512]; char parent_path[512]; char type[128]; uint8_t num_pl_slots; uint8_t num_aie_slots; int active; int wd; //inotify watch desc int load_base_design; slot_info_t **slots; uint64_t inter_rp_comm[RP_SLOTS_MAX]; /**< Inter-RP buffer addrs */ accel_info_t accel_list[RP_SLOTS_MAX]; }; typedef struct { char boardName[128]; struct basePLDesign* active_base; }platform_info_t; struct daemon_config { char defaul_accel_name[64]; char **firmware_locations; int number_locations; }; #ifdef __cplusplus } #endif #endif dfx-mgr-xilinx_v2023.2/src/print.h000066400000000000000000000027071446677152000170450ustar00rootroot00000000000000/* * Copyright (c) 2021, Xilinx Inc. and Contributors. All rights reserved. * * SPDX-License-Identifier: MIT */ /* * @file print.h * @brief print definition */ #ifndef _ACAPD_PRINT_H #define _ACAPD_PRINT_H #ifdef __cplusplus extern "C" { #endif #define INFO(...) \ fprintf(stderr, "Info: %s:\n%d:%s:\n ", __FILE__, __LINE__, __func__); \ fprintf(stderr, __VA_ARGS__); #define INFOP(...) \ fprintf(stderr, __VA_ARGS__); #define DEBUG #ifndef DEBUG #define acapd_debug(...) #define acapd_praw(...) #else void acapd_debug(const char *format, ...); #define acapd_praw printf #endif /* DEBUG */ void acapd_print(const char *format, ...); void acapd_perror(const char *format, ...); /** * Convenience macros DFX_ERR, DFX_PR, DFX_DBG to add source * function name and the line number before the message. * Inspired by pr_err, etc. in the kernel's printk.h. */ #ifdef errno #define DFX_ERR(fmt, args ...) do { fprintf(stderr, \ "DFX-MGRD> ERROR:%s():%u " fmt ": %s\n", \ __func__, __LINE__, ##args, errno ? strerror(errno) : ""); \ } while (0) #else /* errno */ #define DFX_ERR(fmt, args ...) fprintf(stderr, \ "DFX-MGRD> ERROR:%s():%u " fmt "\n", \ __func__, __LINE__, ##args) #endif /* errno */ #define DFX_PR(fmt, args ...) printf("DFX-MGRD> %s():%u " fmt "\n", \ __func__, __LINE__, ##args) #ifdef DEBUG #define DFX_DBG DFX_PR #else #define DFX_DBG(fmt, args ...) #endif /* DEBUG */ #ifdef __cplusplus } #endif #endif /* _ACAPD_PRINT_H */ dfx-mgr-xilinx_v2023.2/src/scripts/000077500000000000000000000000001446677152000172215ustar00rootroot00000000000000dfx-mgr-xilinx_v2023.2/src/scripts/xlnx-firmware-detect000077500000000000000000000044061446677152000232240ustar00rootroot00000000000000#!/bin/sh # (C) Copyright 2022 Xilinx, Inc. # SPDX-License-Identifier: MIT # read values from dfx-mgr conf file conffile="/etc/dfx-mgrd/daemon.conf" if [ ! -f "${conffile}" ]; then echo "dfx-mgrd configuration file not found: ${conffile}" exit 1 fi fwbasedir=$(grep "firmware_location" ${conffile} | sed 's/.*:.*\[\"\(.*\)\"\],\?/\1/') if [ -z "${fwbasedir}" ]; then echo "Property 'firmware_location' not found in ${conffile}" exit 1 fi fwfile=$(grep "default_accel" ${conffile} | sed 's/.*:.*\"\(.*\)\",\?/\1/') if [ -z "${fwfile}" ]; then echo "Property 'default_accel' not found in ${conffile}" exit 1 fi # check if default firmware is already set and present if [ -f "${fwfile}" ]; then fwname=$(cat ${fwfile}) fwdir="${fwbasedir}/${fwname}" if [ -n "${fwname}" ] && [ -d "${fwdir}" ]; then echo "Default firmware detected: ${fwname}" exit 0 fi fi # search for firmware based on EEPROM board id echo "Trying to detect default firmware based on EEPROM..." # check if board is a SOM product eeprom=$(ls /sys/bus/i2c/devices/*50/eeprom 2> /dev/null) if [ -n "${eeprom}" ]; then boardid=$(ipmi-fru --fru-file=${eeprom} --interpret-oem-data | awk -F"-" '/FRU Board Product/ { print tolower($2) }') fwname="${boardid}-starter-kits" fwdir="${fwbasedir}/${fwname}" if [ ! -d "${fwdir}" ]; then echo "No default firmware named ${fwname} found in ${fwbasedir}" exit 1 fi echo "Default firmware detected: ${fwname}" echo "${fwname}" > "${fwfile}" exit 0 fi # check if board is a System Controller product eeprom=$(ls /sys/bus/i2c/devices/*54/eeprom 2> /dev/null) if [ -n "${eeprom}" ]; then boardid=$(ipmi-fru --fru-file=${eeprom} --interpret-oem-data | awk -F": " '/FRU Board Product/ { print tolower ($2) }') revision=$(ipmi-fru --fru-file=${eeprom} --interpret-oem-data | awk -F": " '/FRU Board Custom/ { print tolower ($2); exit }') fwname="${boardid}-${revision}" fwdir="${fwbasedir}/${fwname}" if [ ! -d "${fwdir}" ]; then echo "No default firmware named ${fwname} found in ${fwbasedir}" exit 1 fi echo "Default firmware detected: ${fwname}" echo "${fwname}" > "${fwfile}" exit 0 fi echo "No known Board ID found" exit 1 dfx-mgr-xilinx_v2023.2/src/shell.c000066400000000000000000000102021446677152000170000ustar00rootroot00000000000000/* * Copyright (c) 2021, Xilinx Inc. and Contributors. All rights reserved. * * SPDX-License-Identifier: MIT */ #include #include #include #include #include #include #include static acapd_shell_t shell; int acapd_shell_config(const char *config) { return sys_shell_config(&shell, config); } int acapd_shell_fd() { return shell.dev.id; } int acapd_shell_clock_fd() { return shell.clock_dev.id; } int dfx_shell_fd_by_name(const char *str) { int fd = -1; if (shell.dev.dev_name && strstr(shell.dev.dev_name, str)) fd = shell.dev.id; if (shell.clock_dev.dev_name && strstr(shell.clock_dev.dev_name, str)) fd = shell.clock_dev.id; return fd; } char * dfx_shell_uio_by_name(const char *str) { if (shell.dev.dev_name && strstr(shell.dev.dev_name, str)) return shell.dev.path; if (shell.clock_dev.dev_name && strstr(shell.clock_dev.dev_name, str)) return shell.clock_dev.path; return NULL; } void dfx_shell_uio_list(char *buf, size_t sz) { /* * Assume strlen(..dev_name) < sizeof(shell.dev.path) and * we need to print two pairs: 4 * bigger_size should work */ assert(sz > 4 * sizeof(shell.dev.path)); if (shell.dev.dev_name) buf += sprintf(buf, "%-30s %s\n", shell.dev.dev_name, shell.dev.path); if (shell.clock_dev.dev_name) sprintf(buf, "%-30s %s\n", shell.clock_dev.dev_name, shell.clock_dev.path); } int acapd_shell_release_isolation(acapd_accel_t *accel) { void *reg_va; acapd_device_t *dev; acapd_shell_regs_t regs; //uint32_t v; int i, ret; acapd_assert(accel != NULL); dev = &shell.dev; DFX_DBG("%s", dev->dev_name); if (!shell.slot_regs){ DFX_ERR("%s no isolation_slots in shell.json?", dev->dev_name); return 0; // or ACAPD_ACCEL_FAILURE; } regs = shell.slot_regs[accel->rm_slot]; reg_va = dev->va; if (reg_va == NULL) { ret = acapd_device_open(dev); if (ret < 0) { DFX_ERR("acapd_device_open %s", dev->dev_name); return ACAPD_ACCEL_FAILURE; } reg_va = dev->va; if (reg_va == NULL) { DFX_ERR("shell dev %s va is NULL", dev->dev_name); return ACAPD_ACCEL_FAILURE; } ret = acapd_device_open(&shell.clock_dev); if (ret < 0) { DFX_ERR("acapd_device_open clock_dev %s", shell.clock_dev.dev_name); return ACAPD_ACCEL_FAILURE; } } DFX_DBG("release isolation: (%p)", reg_va); for (i=0; i<4; i++){ *((volatile uint32_t *)((char *)reg_va + regs.offset[i])) = regs.values[i]; } //while(1) { // v = *((volatile uint32_t *)((char *)reg_va + regs->clock_status)); // if ((v & regs->clock_release_mask) != 0) { // break; // } //} //*((volatile uint32_t *)((char *)reg_va + regs->reset_release)) = 0x1; //while(1) { // v = *((volatile uint32_t *)((char *)reg_va + regs->reset_status)); // if ((v & regs->reset_release_mask) != 0) { // break; // } //} DFX_DBG("release isolation done: (%p)", reg_va); return 0; } int acapd_shell_assert_isolation(acapd_accel_t *accel) { void *reg_va; acapd_device_t *dev; //uint32_t v; acapd_shell_regs_t regs; int i; acapd_assert(accel != NULL); dev = &(shell.dev); DFX_DBG("%s", dev->dev_name); if (!shell.slot_regs){ DFX_ERR("%s no isolation_slots in shell.json?", dev->dev_name); return 0; // or ACAPD_ACCEL_FAILURE; } regs = shell.slot_regs[accel->rm_slot]; reg_va = dev->va; if (reg_va == NULL) { int ret; ret = acapd_device_open(dev); if (ret < 0) { DFX_ERR("failed to open shell dev %s.\n", dev->dev_name); return ACAPD_ACCEL_FAILURE; } reg_va = dev->va; if (reg_va == NULL) { DFX_ERR("shell dev %s va is NULL.\n", dev->dev_name); return ACAPD_ACCEL_FAILURE; } } DFX_DBG("assert isolation: (%p)", reg_va); for (i=0; i<4; i++){ *((volatile uint32_t *)((char *)reg_va + regs.offset[i])) = 0; } //while(1) { // v = *((volatile uint32_t *)((char *)reg_va + regs->clock_status)); // if ((v & regs->clock_release_mask) == 0) { // break; // } //} //*((volatile uint32_t *)((char *)reg_va + regs->reset_release)) = 0; //while(1) { // v = *((volatile uint32_t *)((char *)reg_va + regs->reset_status)); // if ((v & regs->reset_release_mask) == 0) { // break; // } //} return 0; } dfx-mgr-xilinx_v2023.2/src/shell.h000066400000000000000000000022011446677152000170050ustar00rootroot00000000000000/* * Copyright (c) 2021, Xilinx Inc. and Contributors. All rights reserved. * * SPDX-License-Identifier: MIT */ /* * @file shell.h * @brief shell primitives. */ #ifndef _ACAPD_SHELL_H #define _ACAPD_SHELL_H #ifdef __cplusplus extern "C" { #endif /** \defgroup shell SHELL Interfaces * @{ */ #include typedef struct acapd_shell_regs { uint32_t *offset; uint32_t *values; } acapd_shell_regs_t; typedef struct acapd_shell { acapd_device_t dev; acapd_device_t clock_dev; char *type; const acapd_shell_regs_t *slot_regs; int is_configured; } acapd_shell_t; int acapd_shell_config(const char *config); int acapd_shell_get(); int acapd_shell_put(); int acapd_shell_clock_fd(); int acapd_shell_fd(); int dfx_shell_fd_by_name(const char *); void dfx_shell_uio_list(char *, size_t); char *dfx_shell_uio_by_name(const char *); int acapd_shell_release_isolation(acapd_accel_t *accel); int acapd_shell_assert_isolation(acapd_accel_t *accel); #ifdef ACAPD_INTERNAL int sys_shell_config(acapd_shell_t *shell, const char *config); #endif /* ACAPD_INTERNAL */ /** @} */ #ifdef __cplusplus } #endif #endif /* _ACAPD_SHELL_H */ dfx-mgr-xilinx_v2023.2/src/shm.c000066400000000000000000000170721446677152000164740ustar00rootroot00000000000000/* * Copyright (c) 2021, Xilinx Inc. and Contributors. All rights reserved. * * SPDX-License-Identifier: MIT */ #include #include #include #include #include #include #include #include #include int acapd_alloc_shm(char *shm_allocator_name, acapd_shm_t *shm, size_t size, uint32_t attr) { (void)shm_allocator_name; shm->refcount = 0; acapd_list_init(&shm->refs); return acapd_default_shm_allocator.alloc(&acapd_default_shm_allocator, shm, size, attr); } int acapd_free_shm(acapd_shm_t *shm) { acapd_list_t *node; /* Detach shared memory first */ acapd_list_for_each(&shm->refs, node) { acapd_device_t *dev; dev = (acapd_device_t *)acapd_container_of(node, acapd_chnl_t, node); if (dev->ops && dev->ops->detach) { dev->ops->detach(dev, shm); } } shm->refcount = 0; acapd_list_init(&shm->refs); acapd_default_shm_allocator.free(&acapd_default_shm_allocator, shm); return 0; } void *acapd_attach_shm(acapd_chnl_t *chnl, acapd_shm_t *shm) { if (chnl == NULL) { acapd_perror("%s: failed, chnl is NULL.\n", __func__); return NULL; } if (shm == NULL) { acapd_perror("%s: failed due to shm is NULL\n", __func__); return NULL; } return acapd_dma_attach(chnl, shm); } int acapd_detach_shm(acapd_chnl_t *chnl, acapd_shm_t *shm) { if (chnl == NULL) { acapd_perror("%s: failed, chnl is NULL.\n", __func__); return -EINVAL; } if (shm == NULL) { acapd_perror("%s: failed due to shm is NULL\n", __func__); return -EINVAL; } return acapd_dma_detach(chnl, shm); } void *acapd_accel_alloc_shm(acapd_accel_t *accel, size_t size, acapd_shm_t *shm) { int ret; (void)accel; if (shm == NULL) { acapd_perror("%s: failed due to shm is NULL\n", __func__); return NULL; } /* We can not use memset to clear memory here as some variables of shm * structure are required to be defined at this point for example FD. */ ret = acapd_alloc_shm(NULL, shm, size, 0); if (ret < 0) { acapd_perror("%s: failed to allocal memory.\n", __func__); return NULL; } /* TODO: if it is DMA buf, it will need to import the DMA buf * to a device e.g. DMA device before it can get the va. */ if (shm->va == NULL) { acapd_perror("%s: va is NULL.\n", __func__); return NULL; } return shm->va; } int acapd_accel_write_data(acapd_accel_t *accel, acapd_shm_t *shm, void *va, size_t size, int wait_for_complete, uint8_t tid) { acapd_chnl_t *chnl = NULL; acapd_dma_config_t config; int ret; void *retva; int transfered_len; if (accel == NULL) { acapd_perror("%s: fafiled due to accel is NULL.\n", __func__); return -EINVAL; } if (accel->chnls == NULL) { acapd_perror("%s: accel doesn't have channels.\n", __func__); return -EINVAL; } /* Assuming only two channels, tx and rx in the list */ for (int i = 0; i < accel->num_chnls; i++) { acapd_chnl_t *lchnl; lchnl = &accel->chnls[i]; if (lchnl->dir == ACAPD_DMA_DEV_W) { chnl = lchnl; break; } } if (chnl == NULL) { acapd_perror("%s: no write channel is found.\n", __func__); return -EINVAL; } acapd_debug("%s: opening chnnl\n", __func__); ret = acapd_dma_open(chnl); if (ret < 0) { acapd_perror("%s: failed to open channel.\n", __func__); return -EINVAL; } acapd_debug("%s: attaching shm to channel\n", __func__); retva = acapd_attach_shm(chnl, shm); if (retva == NULL) { acapd_perror("%s: failed to attach tx shm\n", __func__); return -EINVAL; } /* Check if it is ok to transfer data */ acapd_debug("%s: polling channel status\n", __func__); ret = acapd_dma_poll(chnl, 0, NULL, 0); if (ret < 0) { acapd_perror("%s: chnl is not ready\n", __func__); return -EINVAL; } else if (ret == (int)ACAPD_CHNL_INPROGRESS) { return -EBUSY; } acapd_debug("%s: transfer data\n", __func__); acapd_dma_init_config(&config, shm, va, size, tid); ret = acapd_dma_transfer(chnl, &config); if (ret < 0) { acapd_perror("%s: failed to transfer data\n", __func__); return -EINVAL; } transfered_len = ret; if (wait_for_complete != 0) { /* Wait until data has been sent*/ acapd_debug("%s: wait for chnl to complete\n", __func__); ret = acapd_dma_poll(chnl, 1, NULL, 0); if (ret < 0) { acapd_perror("%s: chnl is not done successfully\n", __func__); return -EINVAL; } } return transfered_len; } int acapd_accel_read_data(acapd_accel_t *accel, acapd_shm_t *shm, void *va, size_t size, int wait_for_complete) { acapd_chnl_t *chnl = NULL; acapd_dma_config_t config; int ret; int transfered_len = 0; void *retva; if (accel == NULL) { acapd_perror("%s: fafiled due to accel is NULL.\n", __func__); return -EINVAL; } if (accel->chnls == NULL) { acapd_perror("%s: accel doesn't have channels.\n", __func__); return -EINVAL; } /* Assuming only two channels, tx and rx in the list */ for (int i = 0; i < accel->num_chnls; i++) { acapd_chnl_t *lchnl; lchnl = &accel->chnls[i]; if (lchnl->dir == ACAPD_DMA_DEV_R) { chnl = lchnl; break; } } if (chnl == NULL) { acapd_perror("%s: no write channel is found.\n", __func__); return -EINVAL; } acapd_debug("%s: opening chnnl\n", __func__); ret = acapd_dma_open(chnl); if (ret < 0) { acapd_perror("%s: failed to open channel.\n", __func__); return -EINVAL; } /* Attach memory to the channel */ acapd_debug("%s: attaching memory to chnnl\n", __func__); retva = acapd_attach_shm(chnl, shm); if (retva == NULL) { acapd_perror("%s: failed to attach rx shm\n", __func__); return -EINVAL; } /* Check if it is ok to transfer data */ acapd_debug("%s: check if chnl is ready to receive data.\n", __func__); ret = acapd_dma_poll(chnl, 0, NULL, 0); if (ret < 0) { acapd_perror("%s: chnl is not ready\n", __func__); return -EINVAL; } else if (ret == (int)ACAPD_CHNL_INPROGRESS) { return -EBUSY; } /* Config channel to receive data */ acapd_debug("%s: transfer data\n", __func__); acapd_dma_init_config(&config, shm, va, size, 0); ret = acapd_dma_transfer(chnl, &config); if (ret < 0) { acapd_perror("%s: failed to transfer data\n", __func__); return -EINVAL; } transfered_len = ret; if (wait_for_complete != 0) { /* Wait until data has been received */ acapd_debug("%s: wait for chnl to complete\n", __func__); ret = acapd_dma_poll(chnl, 1, NULL, 0); if (ret < 0) { acapd_perror("%s: chnl is not done successfully\n", __func__); return -EINVAL; } } return transfered_len; } int acapd_accel_read_complete(acapd_accel_t *accel) { acapd_chnl_t *chnl = NULL; int ret; int transfered_len = 0; if (accel == NULL) { acapd_perror("%s: fafiled due to accel is NULL.\n", __func__); return -EINVAL; } if (accel->chnls == NULL) { acapd_perror("%s: accel doesn't have channels.\n", __func__); return -EINVAL; } /* Assuming only two channels, tx and rx in the list */ for (int i = 0; i < accel->num_chnls; i++) { acapd_chnl_t *lchnl; lchnl = &accel->chnls[i]; if (lchnl->dir == ACAPD_DMA_DEV_R) { chnl = lchnl; break; } } if (chnl == NULL) { acapd_perror("%s: no write channel is found.\n", __func__); return -EINVAL; } acapd_debug("%s: opening chnnl\n", __func__); ret = acapd_dma_open(chnl); if (ret < 0) { acapd_perror("%s: failed to open channel.\n", __func__); return -EINVAL; } /* Wait until data has been received */ acapd_debug("%s: wait for chnl to complete\n", __func__); ret = acapd_dma_poll(chnl, 1, NULL, 0); if (ret < 0) { acapd_perror("%s: chnl is not done successfully\n", __func__); return -EINVAL; } acapd_debug("%s: channel is complete\n", __func__); return transfered_len; } dfx-mgr-xilinx_v2023.2/src/shm.h000066400000000000000000000044121446677152000164730ustar00rootroot00000000000000/* * Copyright (c) 2021, Xilinx Inc. and Contributors. All rights reserved. * * SPDX-License-Identifier: MIT */ /* * @file shm.h * @brief shared memory definition. */ #ifndef _ACAPD_SHM_H #define _ACAPD_SHM_H #ifdef __cplusplus extern "C" { #endif #include #include #include #include typedef struct acapd_shm acapd_shm_t; /** Shared memory provider data structure. */ typedef struct acapd_shm_allocator acapd_shm_allocator_t; typedef struct acapd_shm_allocator { const char *name; /**< name of shmem provider */ void *priv; /**< private data */ int (*alloc)(acapd_shm_allocator_t *allocator, acapd_shm_t *shm, size_t size, uint32_t attr); /**< shmem allocation function */ void (*free)(acapd_shm_allocator_t *allocator, acapd_shm_t *shm); /**< shmem free function */ acapd_list_t node; /**< node */ } acapd_shm_allocator_t; /** ACPAD shared memory data structure. */ typedef struct acapd_shm { char *name; /**< shared memory name */ char *va; /**< shared memory virtual address */ size_t size; /**< shared memory size */ unsigned int flags; /**< shared memory flag, cacheable, or noncacheable */ int id; /**< shared memory id */ int refcount; /**< reference count */ acapd_shm_allocator_t *allocator; /**< allocator where this shared memory is from */ acapd_list_t refs; /**< attached acapd channels references list */ } acapd_shm_t; extern acapd_shm_allocator_t acapd_default_shm_allocator; int acapd_alloc_shm(char *shm_allocator_name, acapd_shm_t *shm, size_t size, uint32_t attr); int acapd_free_shm(acapd_shm_t *shm); void *acapd_attach_shm(acapd_chnl_t *chnl, acapd_shm_t *shm); int acapd_detach_shm(acapd_chnl_t *chnl, acapd_shm_t *shm); int acapd_sync_shm_device(acapd_shm_t *shm, acapd_chnl_t *chnl); //High level api's void *acapd_accel_alloc_shm(acapd_accel_t *accel, size_t size, acapd_shm_t *shm); int acapd_accel_write_data(acapd_accel_t *accel, acapd_shm_t *shm, void *va, size_t size, int wait_for_complete, uint8_t tid); int acapd_accel_read_data(acapd_accel_t *accel, acapd_shm_t *shm, void *va, size_t size, int wait_for_complete); int acapd_accel_read_complete(acapd_accel_t *accel); #ifdef __cplusplus } #endif #endif /* _ACAPD_SHM_H */ dfx-mgr-xilinx_v2023.2/src/sys/000077500000000000000000000000001446677152000163505ustar00rootroot00000000000000dfx-mgr-xilinx_v2023.2/src/sys/CMakeLists.txt000066400000000000000000000001151446677152000211050ustar00rootroot00000000000000add_subdirectory (${PROJECT_SYSTEM}) # vim: expandtab:ts=2:sw=2:smartindent dfx-mgr-xilinx_v2023.2/src/sys/generic/000077500000000000000000000000001446677152000177645ustar00rootroot00000000000000dfx-mgr-xilinx_v2023.2/src/sys/generic/CMakeLists.txt000066400000000000000000000012631446677152000225260ustar00rootroot00000000000000######################################################################### # Copyright (c) 2021, Xilinx Inc. and Contributors. All rights reserved. # SPDX-License-Identifier: MIT ######################################################################### collect (PROJECT_LIB_HEADERS accel.h) collect (PROJECT_LIB_HEADERS dma.h) collect (PROJECT_LIB_HEADERS generic-device.h) collect (PROJECT_LIB_SOURCES accel.c) collect (PROJECT_LIB_SOURCES dma-axidma.c) collect (PROJECT_LIB_SOURCES device.c) collect (PROJECT_LIB_SOURCES json-config.c) collect (PROJECT_LIB_SOURCES print.c) collect (PROJECT_LIB_SOURCES shell.c) collect (PROJECT_LIB_SOURCES shm.c) # vim: expandtab:ts=2:sw=2:smartindent dfx-mgr-xilinx_v2023.2/src/sys/generic/accel.c000066400000000000000000000065211446677152000212030ustar00rootroot00000000000000/* * Copyright (c) 2019, Xilinx Inc. and Contributors. All rights reserved. * * SPDX-License-Identifier: MIT */ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #define DTBO_ROOT_DIR "/sys/kernel/config/device-tree/overlays" int sys_needs_load_accel(acapd_accel_t *accel) { /* Always loads accel */ (void)accel; return 1; } int sys_accel_config(acapd_accel_t *accel) { acapd_accel_sys_t *sys_pkg; const char *json_config; int ret; acapd_assert(accel != NULL); acapd_assert(accel->pkg != NULL); sys_pkg = (acapd_accel_sys_t *)(accel->pkg); acapd_assert(sys_pkg->accel_json_pa != 0); acapd_assert(sys_pkg->accel_json_size != 0); json_config = (const char *)((uintptr_t)sys_pkg->accel_json_pa); ret = parseAccelJson(accel, json_config, (size_t)sys_pkg->accel_json_size); for (int i = 0; i < accel->num_ip_devs; i++) { acapd_device_t *dev; dev = &(accel->ip_dev[i]); dev->va = (void*)((uintptr_t)(dev->reg_pa)); acapd_debug("%s: ipdev[%d], %p:0x%lx.\n", __func__, i, dev->va, dev->reg_pa); } for (int i = 0; i < accel->num_chnls; i++) { acapd_chnl_t *chnl; acapd_device_t *dev; chnl = &(accel->chnls[i]); dev = chnl->dev; dev->va = (void *)((uintptr_t)(dev->reg_pa)); acapd_debug("%s: channel[%d], %p:0x%lx.\n", __func__, i, dev->va, dev->reg_pa); } return ret; } int sys_fetch_accel(acapd_accel_t *accel) { (void)accel; return ACAPD_ACCEL_SUCCESS; } int sys_load_accel(acapd_accel_t *accel, unsigned int async) { XFpga XFpgaInst = {0}; //const char *pdi; int ret; acapd_accel_sys_t *sys_pkg; acapd_assert(accel != NULL); acapd_assert(accel->pkg != NULL); /* TODO: only support synchronous mode for now */ (void)async; sys_pkg = (acapd_accel_sys_t *)(accel->pkg); acapd_assert(sys_pkg->accel_pdi_pa != 0); acapd_assert(sys_pkg->accel_pdi_size != 0); acapd_debug("%s: pdi pa: 0x%llx, size=0x%llx.\n", __func__, sys_pkg->accel_pdi_pa, sys_pkg->accel_pdi_size); //pdi = (const char *)((uintptr_t)sys_pkg->accel_pdi_pa); #if 0 if (pkg->type != ACAPD_ACCEL_PKG_TYPE_PDI) { acapd_perror("Failed to load accel, none supported type %u.\n", pkg->type); return ACAPD_ACCEL_FAILURE; } #endif ret = XFpga_Initialize(&XFpgaInst); if (ret != XST_SUCCESS) { acapd_perror("Failed to init fpga instance.\n"); accel->status = ACAPD_ACCEL_STATUS_UNLOADED; accel->load_failure = ACAPD_ACCEL_INVALID; return ACAPD_ACCEL_FAILURE; } #if 0 ret = XFpga_PL_BitStream_Load(&XFpgaInst, (UINTPTR)((char *)pkg + sizeof(*pkg)), 0, 1); #else ret = XFpga_PL_BitStream_Load(&XFpgaInst, sys_pkg->accel_pdi_pa, 0, 0); #endif if (ret != XFPGA_SUCCESS) { return ACAPD_ACCEL_FAILURE; } else { /* TODO: FIXME: hardcoded to release isolation */ //Xil_Out32(0x90010000, 0x1); //Xil_Out32(0x90000000, 0x1); return ACAPD_ACCEL_SUCCESS; } } int sys_load_accel_post(acapd_accel_t *accel) { (void)accel; return 0; } int sys_close_accel(acapd_accel_t *accel) { (void)accel; return 0; } int sys_remove_accel(acapd_accel_t *accel, unsigned int async) { /* TODO: Do nothing for now */ (void)async; (void)accel; return ACAPD_ACCEL_SUCCESS; } dfx-mgr-xilinx_v2023.2/src/sys/generic/accel.h000066400000000000000000000007701446677152000212100ustar00rootroot00000000000000/* * Copyright (c) 2019, Xilinx Inc. and Contributors. All rights reserved. * * SPDX-License-Identifier: MIT */ /* * @file linux/accel.h * @brief Linux specific accelerator definition. */ #ifndef _ACAPD_LINUX_ACCEL_H #define _ACAPD_LINUX_ACCEL_H #include /** * @brief accel system specific information */ typedef struct { uint64_t accel_json_pa; uint64_t accel_json_size; uint64_t accel_pdi_pa; uint64_t accel_pdi_size; } acapd_accel_sys_t; #endif /* _ACAPD_LINUX_ACCEL_H */ dfx-mgr-xilinx_v2023.2/src/sys/generic/device.c000066400000000000000000000033411446677152000213700ustar00rootroot00000000000000/* * Copyright (c) 2019, Xilinx Inc. and Contributors. All rights reserved. * * SPDX-License-Identifier: MIT */ #include #include #include #include #include #include "generic-device.h" #include #include #include #include #include int sys_device_open(acapd_device_t *dev) { acapd_assert(dev != NULL); if (dev->ops != NULL && dev->ops->open != NULL) { return dev->ops->open(dev); } if (dev->ops != NULL) { return 0; } dev->ops = &sys_generic_dev_ops; return dev->ops->open(dev); } static int sys_generic_device_open(acapd_device_t *dev) { if (dev == NULL) { acapd_perror("%s: dev pointer is NULL.\n", __func__); return -EINVAL; } if (dev->va == NULL) { acapd_perror("%s: dev va is NULL.\n", __func__); return -EINVAL; } dev->priv = dev->va; return 0; } static int sys_generic_device_close(acapd_device_t *dev) { if (dev == NULL) { acapd_perror("%s: dev is NULL.\n", __func__); return -EINVAL; } return 0; } static void *sys_generic_device_attach(acapd_device_t *dev, acapd_shm_t *shm) { (void)dev; if (shm == NULL) { acapd_perror("%s: shm is NULL.\n", __func__); return NULL; } return shm->va; } static int sys_generic_device_detach(acapd_device_t *dev, acapd_shm_t *shm) { (void)dev; (void)shm; return 0; } static uint64_t sys_generic_device_va_to_da(acapd_device_t *dev, void *va) { (void)dev; return (uint64_t)((uintptr_t)va); } acapd_device_ops_t sys_generic_dev_ops = { .open = sys_generic_device_open, .close = sys_generic_device_close, .attach = sys_generic_device_attach, .detach = sys_generic_device_detach, .va_to_da = sys_generic_device_va_to_da, }; dfx-mgr-xilinx_v2023.2/src/sys/generic/dma-axidma.c000066400000000000000000000230401446677152000221310ustar00rootroot00000000000000/* * Copyright (c) 2019, Xilinx Inc. and Contributors. All rights reserved. * * SPDX-License-Identifier: MIT */ #include #include #include #include #include #include #include #include #include #include #define XAXIDMA_TX_OFFSET 0x00000000 /**< TX channel registers base * offset */ #define XAXIDMA_RX_OFFSET 0x00000030 /**< RX channel registers base * offset */ #define XAXIDMA_CR_OFFSET 0x00000000 /**< Channel control */ #define XAXIDMA_SR_OFFSET 0x00000004 /**< Status */ #define XAXIDMA_CDESC_OFFSET 0x00000008 /**< Current descriptor pointer */ #define XAXIDMA_CDESC_MSB_OFFSET 0x0000000C /**< Current descriptor pointer */ #define XAXIDMA_TDESC_OFFSET 0x00000010 /**< Tail descriptor pointer */ #define XAXIDMA_TDESC_MSB_OFFSET 0x00000014 /**< Tail descriptor pointer */ #define XAXIDMA_SRCADDR_OFFSET 0x00000018 /**< Simple mode source address pointer */ #define XAXIDMA_SRCADDR_MSB_OFFSET 0x0000001C /**< Simple mode source address pointer */ #define XAXIDMA_DESTADDR_OFFSET 0x00000018 /**< Simple mode destination address pointer */ #define XAXIDMA_DESTADDR_MSB_OFFSET 0x0000001C /**< Simple mode destination address pointer */ #define XAXIDMA_BUFFLEN_OFFSET 0x00000028 /**< Tail descriptor pointer */ #define XAXIDMA_SGCTL_OFFSET 0x0000002c /**< SG Control Register */ #define XAXIDMA_CR_RUNSTOP_MASK 0x00000001 /**< Start/stop DMA channel */ #define XAXIDMA_CR_RESET_MASK 0x00000004 /**< Reset DMA engine */ #define XAXIDMA_CR_KEYHOLE_MASK 0x00000008 /**< Keyhole feature */ #define XAXIDMA_CR_CYCLIC_MASK 0x00000010 /**< Cyclic Mode */ #define XAXIDMA_HALTED_MASK 0x00000001 /**< DMA channel halted */ #define XAXIDMA_IDLE_MASK 0x00000002 /**< DMA channel idle */ #define XAXIDMA_ERR_INTERNAL_MASK 0x00000010 /**< Datamover internal * err */ #define XAXIDMA_ERR_SLAVE_MASK 0x00000020 /**< Datamover slave err */ #define XAXIDMA_ERR_DECODE_MASK 0x00000040 /**< Datamover decode * err */ #define XAXIDMA_ERR_SG_INT_MASK 0x00000100 /**< SG internal err */ #define XAXIDMA_ERR_SG_SLV_MASK 0x00000200 /**< SG slave err */ #define XAXIDMA_ERR_SG_DEC_MASK 0x00000400 /**< SG decode err */ #define XAXIDMA_ERR_ALL_MASK 0x00000770 /**< All errors */ static int axidma_generic_transfer(acapd_chnl_t *chnl, acapd_dma_config_t *config) { acapd_device_t *dev; void *base_va; /**< AXI DMA reg mmaped base va address */ uint32_t v; uint64_t da; void *va; size_t size; acapd_assert(chnl != NULL); acapd_assert(chnl->dev != NULL); acapd_assert(chnl->dev->va != NULL); acapd_assert(chnl->dev->ops != NULL); acapd_assert(chnl->dev->ops->va_to_da != NULL); dev = chnl->dev; base_va = dev->va; va = config->va; size = config->size; da = dev->ops->va_to_da(dev, va); if (da == (uint64_t)(-1)) { acapd_perror("%s: failed to get da from va %p.\n", __func__, va); return -EINVAL; } if (chnl->dir == ACAPD_DMA_DEV_W) { acapd_debug("%s(%p): data from da 0x%llx,0x%llx to stream.\n", __func__, dev->va, da, size); Xil_DCacheFlushRange((uintptr_t)va, size); /* write to stream, setup tx DMA */ base_va = (void *)((char *)base_va + XAXIDMA_TX_OFFSET); v = *((volatile uint32_t *)((char *)base_va + XAXIDMA_CR_OFFSET)); v |= XAXIDMA_CR_RUNSTOP_MASK; *((volatile uint32_t *)((char *)base_va + XAXIDMA_CR_OFFSET)) = v; v = *((volatile uint32_t *)((char *)base_va + XAXIDMA_SR_OFFSET)); if ((v & XAXIDMA_HALTED_MASK) != 0) { acapd_perror("%s: tx failed due to chnl is halted.\n", __func__); return -EINVAL; } *((volatile uint32_t *)((char *)base_va + XAXIDMA_SRCADDR_OFFSET)) = (uint32_t)(da & 0xFFFFFFFF); *((uint32_t *)((char *)base_va + XAXIDMA_SRCADDR_MSB_OFFSET)) = (uint32_t)((da & 0xFFFFFFFF00000000) >> 32); *((uint32_t *)((char *)base_va + XAXIDMA_BUFFLEN_OFFSET)) = size; } else { acapd_debug("%s(%p): data from stream to da 0x%llx, 0x%llx.\n", __func__, dev->va, da, size); Xil_DCacheInvalidateRange((uintptr_t)va, size); /* read from stream, setup rx DMA */ base_va = (void *)((char *)base_va + XAXIDMA_RX_OFFSET); v = *((volatile uint32_t *)((char *)base_va + XAXIDMA_CR_OFFSET)); v |= XAXIDMA_CR_RUNSTOP_MASK; *((volatile uint32_t *)((char *)base_va + XAXIDMA_CR_OFFSET)) = v; v = *((uint32_t *)((char *)base_va + XAXIDMA_SR_OFFSET)); if ((v & XAXIDMA_HALTED_MASK) != 0) { acapd_perror("%s: rx failed due to chnl is halted.\n", __func__); return -EINVAL; } *((volatile uint32_t *)((char *)base_va + XAXIDMA_DESTADDR_OFFSET)) = (uint32_t)(da & 0xFFFFFFFF); *((uint32_t *)((char *)base_va + XAXIDMA_DESTADDR_MSB_OFFSET)) = (uint32_t)((da & 0xFFFFFFFF00000000) >> 32); *((uint32_t *)((char *)base_va + XAXIDMA_BUFFLEN_OFFSET)) = size; } return size; } static int axidma_generic_stop(acapd_chnl_t *chnl) { acapd_device_t *dev; void *base_va; /**< AXI DMA reg mmaped base va address */ uint32_t v; acapd_assert(chnl != NULL); acapd_assert(chnl->dev != NULL); acapd_assert(chnl->dev->va != NULL); dev = chnl->dev; base_va = dev->va; if (chnl->dir == ACAPD_DMA_DEV_W) { /* write to stream, stop tx DMA */ base_va = (void *)((char *)base_va + XAXIDMA_TX_OFFSET); v = *((volatile uint32_t *)((char *)base_va + XAXIDMA_CR_OFFSET)); v &= (~XAXIDMA_CR_RUNSTOP_MASK); *((volatile uint32_t *)((char *)base_va + XAXIDMA_CR_OFFSET)) = v; } else { /* read from stream, stop rx DMA */ base_va = (void *)((char *)base_va + XAXIDMA_RX_OFFSET); v = *((volatile uint32_t *)((char *)base_va + XAXIDMA_CR_OFFSET)); v &= (~XAXIDMA_CR_RUNSTOP_MASK); *((volatile uint32_t *)((char *)base_va + XAXIDMA_CR_OFFSET)) = v; } return 0; } static acapd_chnl_status_t axidma_generic_poll(acapd_chnl_t *chnl) { acapd_device_t *dev; void *base_va; /**< AXI DMA reg mmaped base va address */ uint32_t v; acapd_assert(chnl != NULL); acapd_assert(chnl->dev != NULL); acapd_assert(chnl->dev->va != NULL); dev = chnl->dev; base_va = dev->va; if (chnl->dir == ACAPD_DMA_DEV_W) { /* write to stream, read tx DMA status */ base_va = (void *)((char *)base_va + XAXIDMA_TX_OFFSET); v = *((volatile uint32_t *)((char *)base_va + XAXIDMA_CR_OFFSET)); if ((v & XAXIDMA_CR_RUNSTOP_MASK) == 0) { return ACAPD_CHNL_IDLE; } v = *((volatile uint32_t *)((char *)base_va + XAXIDMA_SR_OFFSET)); if ((v & XAXIDMA_ERR_ALL_MASK) != 0) { acapd_perror("%s, tx channel of %s errors: 0x%x\n", __func__, dev->dev_name, v); return ACAPD_CHNL_ERRORS; } else if ((v & XAXIDMA_IDLE_MASK) != 0) { return ACAPD_CHNL_IDLE; } else { return ACAPD_CHNL_INPROGRESS; } } else { /* read from stream, read rx DMA status */ base_va = (void *)((char *)base_va + XAXIDMA_RX_OFFSET); v = *((volatile uint32_t *)((char *)base_va + XAXIDMA_CR_OFFSET)); if ((v & XAXIDMA_CR_RUNSTOP_MASK) == 0) { return ACAPD_CHNL_IDLE; } v = *((volatile uint32_t *)((char *)base_va + XAXIDMA_SR_OFFSET)); if ((v & XAXIDMA_ERR_ALL_MASK) != 0) { acapd_perror("%s, rx channel of %s errors: 0x%x\n", __func__, dev->dev_name, v); return ACAPD_CHNL_ERRORS; } else if ((v & XAXIDMA_IDLE_MASK) != 0) { return ACAPD_CHNL_IDLE; } else { return ACAPD_CHNL_INPROGRESS; } } } static int axidma_generic_reset(acapd_chnl_t *chnl) { acapd_device_t *dev; void *base_va; /**< AXI DMA reg mmaped base va address */ acapd_assert(chnl != NULL); acapd_assert(chnl->dev != NULL); acapd_assert(chnl->dev->va != NULL); dev = chnl->dev; base_va = dev->va; if (chnl->dir == ACAPD_DMA_DEV_W) { /* write to stream, reset tx DMA */ base_va = (void *)((char *)base_va + XAXIDMA_TX_OFFSET); *((volatile uint32_t *)((char *)base_va + XAXIDMA_CR_OFFSET)) = XAXIDMA_CR_RESET_MASK; } else { /* read from stream, reset rx DMA */ base_va = (void *)((char *)base_va + XAXIDMA_RX_OFFSET); *((volatile uint32_t *)((char *)base_va + XAXIDMA_CR_OFFSET)) = XAXIDMA_CR_RESET_MASK; } return 0; } static int axidma_generic_open(acapd_chnl_t *chnl) { acapd_device_t *dev; int ret; acapd_assert(chnl != NULL); acapd_assert(chnl->dev != NULL); dev = chnl->dev; ret = acapd_device_get(dev); if (ret < 0) { acapd_perror("%s: failed to get device %s.\n", __func__, dev->dev_name); return -EINVAL; } if (dev->refs == 1) { /* First time to open channel, reset it */ void *reg_va; /**< AXI DMA reg mmaped base va address */ uint32_t v; reg_va = dev->va; reg_va = (void *)((char *)reg_va + XAXIDMA_TX_OFFSET + XAXIDMA_CR_OFFSET); *((volatile uint32_t *)reg_va) = XAXIDMA_CR_RESET_MASK; acapd_debug("%s: reset DMA %p.\n", __func__, reg_va); do { v = *((volatile uint32_t *)reg_va); } while ((v & XAXIDMA_CR_RESET_MASK) != 0); } return 0; } static int axidma_generic_close(acapd_chnl_t *chnl) { acapd_device_t *dev; int ret; acapd_assert(chnl != NULL); acapd_assert(chnl->dev != NULL); dev = chnl->dev; if (dev->refs == 1) { /* last one to put device, reset it */ void *reg_va; /**< AXI DMA reg mmaped base va address */ uint32_t v; reg_va = dev->va; reg_va = (void *)((char *)reg_va + XAXIDMA_TX_OFFSET + XAXIDMA_CR_OFFSET); *((volatile uint32_t *)reg_va) = XAXIDMA_CR_RESET_MASK; do { v = *((volatile uint32_t *)reg_va); } while ((v & XAXIDMA_CR_RESET_MASK) != 0); } ret = acapd_device_put(dev); return ret; } acapd_dma_ops_t axidma_generic_ops = { .name = "axidma_generic", .transfer = axidma_generic_transfer, .stop = axidma_generic_stop, .poll = axidma_generic_poll, .reset = axidma_generic_reset, .open = axidma_generic_open, .close = axidma_generic_close, }; dfx-mgr-xilinx_v2023.2/src/sys/generic/dma.h000066400000000000000000000005071446677152000207000ustar00rootroot00000000000000/* * Copyright (c) 2020, Xilinx Inc. and Contributors. All rights reserved. * * SPDX-License-Identifier: MIT */ /* * @file generic/dma.h * @brief Generic specific DMA definition. */ #ifndef _ACAPD_GENERIC_DMA_H #define _ACAPD_GENERIC_DMA_H extern acapd_dma_ops_t axidma_generic_ops; #endif /* _ACAPD_LINUX_DMA_H */ dfx-mgr-xilinx_v2023.2/src/sys/generic/generic-device.h000066400000000000000000000005671446677152000230160ustar00rootroot00000000000000/* * Copyright (c) 2020, Xilinx Inc. and Contributors. All rights reserved. * * SPDX-License-Identifier: MIT */ /* * @file acapd-vfio-common.h */ #ifndef _ACAPD_GENERIC_DEVICE_H #define _ACAPD_GENERIC_DEVICE_H #ifdef __cplusplus extern "C" { #endif #include extern acapd_device_ops_t sys_generic_dev_ops; #endif /* _ACAPD_GENERIC_DEVICE_H */ dfx-mgr-xilinx_v2023.2/src/sys/generic/json-config.c000066400000000000000000000143741446677152000223550ustar00rootroot00000000000000/* * Copyright (c) 2019, Xilinx Inc. and Contributors. All rights reserved. * * SPDX-License-Identifier: MIT */ #include #include #include #include #include #include #include #include #include #include #include #include static int jsoneq(const char *json, jsmntok_t *tok, const char *s) { if (tok->type == JSMN_STRING && (int)strlen(s) == tok->end - tok->start && strncmp(json + tok->start, s, tok->end - tok->start) == 0) { return 0; } return -1; } int parseAccelJson(acapd_accel_t *accel, const char *config, size_t csize) { jsmn_parser parser; jsmntok_t token[128]; int ret,i; const char *jsonData; size_t numBytes; acapd_device_t *dma_dev; dma_dev = (acapd_device_t *)calloc(1, sizeof(*dma_dev)); if (dma_dev == NULL) { acapd_perror("%s: failed to alloc mem for dma dev.\n", __func__); return -EINVAL; } jsonData = config; numBytes = csize; acapd_praw("jsonData read:\n %s\n",jsonData); jsmn_init(&parser); ret = jsmn_parse(&parser, jsonData, numBytes, token, sizeof(token)/sizeof(token[0])); if (ret < 0){ acapd_praw("Failed to parse JSON: %d\n", ret); } for(i=1; i < ret; i++){ if (token[i].type == JSMN_OBJECT) continue; if (jsoneq(jsonData, &token[i],"accel_devices") == 0){ int j; int numDevices = token[i+1].size; acapd_device_t *devs; devs = (acapd_device_t *)calloc(numDevices, sizeof(*devs)); if (devs == NULL) { acapd_perror("%s: Failed to alloc mem for accel devs.\n", __func__); ret = -ENOMEM; goto error; } i+=2; accel->num_ip_devs = numDevices; for(j=0; j < numDevices; j++){ if (jsoneq(jsonData, &token[i+j+1],"dev_name") == 0) devs[j].dev_name = strndup(jsonData+token[i+j+2].start, token[i+j+2].end - token[i+j+2].start); if (jsoneq(jsonData, &token[i+j+3],"reg_base") == 0) devs[j].reg_pa = (uint64_t)strtoll(strndup(jsonData+token[i+j+4].start, token[i+j+4].end - token[i+j+4].start), NULL, 16); if (jsoneq(jsonData, &token[i+j+5],"reg_size") == 0) devs[j].reg_size = (size_t)strtoll(strndup(jsonData+token[i+j+6].start, token[i+j+6].end - token[i+j+6].start), NULL, 16); i+=6; } accel->ip_dev = devs; } if (jsoneq(jsonData, &token[i],"accel_reg_base") == 0){} if (jsoneq(jsonData, &token[i],"accel_reg_size") == 0){} if (jsoneq(jsonData, &token[i],"sizeInKB")== 0){} if (jsoneq(jsonData, &token[i],"sharedMemType") == 0){} if (jsoneq(jsonData, &token[i],"dma_dev_name") == 0) dma_dev->dev_name = strndup(jsonData+token[i+1].start, token[i+1].end - token[i+1].start); if (jsoneq(jsonData, &token[i],"dma_driver") == 0) dma_dev->driver = strndup(jsonData+token[i+1].start, token[i+1].end - token[i+1].start); if (jsoneq(jsonData, &token[i],"dma_reg_base") == 0){ dma_dev->reg_pa = (uint64_t)strtoll(strndup(jsonData+token[i+1].start, token[i+1].end - token[i+1].start), NULL, 16); } if (jsoneq(jsonData, &token[i],"dma_reg_size") == 0){ dma_dev->reg_size = (size_t)strtoll(strndup(jsonData+token[i+1].start, token[i+1].end - token[i+1].start), NULL, 16); } if (jsoneq(jsonData, &token[i],"iommu_group") == 0) dma_dev->iommu_group = atoi(strndup(jsonData+token[i+1].start, token[i+1].end - token[i+1].start)); if (jsoneq(jsonData, &token[i],"Bus") == 0){} if (jsoneq(jsonData, &token[i],"HWType") == 0){} if (jsoneq(jsonData, &token[i],"dataMoverCacheCoherent") == 0){} if (jsoneq(jsonData, &token[i],"dataMoverVirtualAddress") == 0){} if (jsoneq(jsonData, &token[i],"dataMoverChnls") == 0){ int j; int numChnls = token[i+1].size; acapd_chnl_t *chnls; chnls = (acapd_chnl_t *)calloc(numChnls, sizeof(*chnls)); if (chnls == NULL) { acapd_perror("%s: failed to alloc mem for chnls.\n", __func__); ret = -ENOMEM; goto error; } i+=2; for(j=0; j < numChnls; j++){ if (jsoneq(jsonData, &token[i+j+1],"chnl_id") == 0){ chnls[j].chnl_id = atoi(strndup(jsonData+token[i+j+2].start, token[i+j+2].end - token[i+j+2].start)); } if (jsoneq(jsonData, &token[i+j+3],"chnl_dir") == 0){ char *dir = strndup(jsonData+token[i+j+4].start, token[i+j+4].end - token[i+j+4].start); if (!strcmp(dir,"ACAPD_DMA_DEV_R")) chnls[j].dir = ACAPD_DMA_DEV_R; else if (!strcmp(dir,"ACAPD_DMA_DEV_W")) chnls[j].dir = ACAPD_DMA_DEV_W; else if (!strcmp(dir,"ACAPD_DMA_DEV_RW")) chnls[j].dir = ACAPD_DMA_DEV_RW; } chnls[j].dev = dma_dev; chnls[j].ops = &axidma_generic_ops; i+=4;//move token to point to next channel in array } accel->num_chnls = numChnls; accel->chnls = chnls; } if (jsoneq(jsonData, &token[i],"AccelHandshakeType") == 0){} if (jsoneq(jsonData, &token[i],"fallbackBehaviour") == 0){} } return 0; error: if (dma_dev != NULL) { free(dma_dev); } if (accel->ip_dev != NULL) { free(accel->ip_dev); accel->ip_dev = NULL; accel->num_ip_devs = 0; } if (accel->chnls != NULL) { free(accel->chnls); accel->chnls = NULL; accel->num_chnls = 0; } return ret; } int parseShellJson(acapd_shell_t *shell, const char *config, size_t csize) { size_t numBytes; jsmn_parser parser; jsmntok_t token[128]; int ret,i; const char *jsonData; acapd_device_t *dev; acapd_assert(shell != NULL); numBytes = csize; jsonData = config; acapd_praw("jsonData read:\n %s\n",jsonData); jsmn_init(&parser); ret = jsmn_parse(&parser, jsonData, numBytes, token, sizeof(token)/sizeof(token[0])); if (ret < 0){ acapd_praw("Failed to parse JSON: %d\n", ret); } dev = &shell->dev; for(i=1; i < ret; i++){ if (token[i].type == JSMN_OBJECT) continue; if (jsoneq(jsonData, &token[i],"device_name") == 0) dev->dev_name = strndup(jsonData+token[i+1].start, token[i+1].end - token[i+1].start); if (jsoneq(jsonData, &token[i],"shell_type") == 0) { acapd_praw("Shell is %s\n",strndup(jsonData+token[i+1].start, token[i+1].end - token[i+1].start)); } if (jsoneq(jsonData, &token[i],"reg_base")== 0) dev->reg_pa = (uint64_t)strtoll(strndup(jsonData+token[i+1].start, token[i+1].end - token[i+1].start), NULL, 16); if (jsoneq(jsonData, &token[i],"reg_size") == 0){} dev->reg_size = (size_t)strtoll(strndup(jsonData+token[i+1].start, token[i+1].end - token[i+1].start), NULL, 16); } return 0; } dfx-mgr-xilinx_v2023.2/src/sys/generic/print.c000066400000000000000000000013331446677152000212640ustar00rootroot00000000000000/* * Copyright (c) 2019, Xilinx Inc. and Contributors. All rights reserved. * * SPDX-License-Identifier: MIT */ #include #include #include #ifdef DEBUG void acapd_debug(const char *format, ...) { va_list argptr; va_start(argptr, format); printf("ACAPD> DEBUG: " ); vprintf(format, argptr); printf("\n" ); va_end(argptr); } #endif void acapd_print(const char *format, ...) { va_list argptr; va_start(argptr, format); printf("ACAPD> " ); vprintf(format, argptr); printf("\n" ); va_end(argptr); } void acapd_perror(const char *format, ...) { va_list argptr; va_start(argptr, format); printf("ACAPD> ERROR: " ); vprintf(format, argptr); printf("\n" ); va_end(argptr); } dfx-mgr-xilinx_v2023.2/src/sys/generic/shell.c000066400000000000000000000017111446677152000212370ustar00rootroot00000000000000/* * Copyright (c) 2019, Xilinx Inc. and Contributors. All rights reserved. * * SPDX-License-Identifier: MIT */ #include #include #include #include #include #include #include #include #include extern unsigned char __START_SHELL_JSON[]; extern unsigned char __END_SHELL_JSON[]; int sys_shell_config(acapd_shell_t *shell, const char *config) { const char *shell_config; size_t csize; int ret; (void)config; acapd_assert(shell != NULL); shell_config = (const char *)__START_SHELL_JSON; csize = __END_SHELL_JSON - __START_SHELL_JSON; ret = parseShellJson(shell, shell_config, csize); if (ret != 0) { return ACAPD_ACCEL_FAILURE; } shell->dev.va = (void *)((uintptr_t)shell->dev.reg_pa); acapd_debug("%s: shell va = %p, pa = 0x%lx.\n", __func__, shell->dev.va, shell->dev.reg_pa); return ACAPD_ACCEL_SUCCESS; } dfx-mgr-xilinx_v2023.2/src/sys/generic/shm.c000066400000000000000000000023221446677152000207160ustar00rootroot00000000000000/* * Copyright (c) 2020, Xilinx Inc. and Contributors. All rights reserved. * * SPDX-License-Identifier: MIT */ #include #include #include #include #include #include static int acapd_generic_alloc_shm(acapd_shm_allocator_t *allocator, acapd_shm_t *shm, size_t size, uint32_t attr) { (void)allocator; (void)attr; if (shm == NULL) { acapd_perror("%s: shm is NULL.\n", __func__); return -EINVAL; } if (shm->id < 0) { shm->id = 0; } shm->va = malloc(size); if (shm->va == NULL) { acapd_perror("%s: failed to allocate memory.\n", __func__); } else { acapd_debug("%s: allocated memory %p, size 0x%x.\n", __func__, shm->va, size); } shm->size = size; return 0; } static void acapd_generic_free_shm(acapd_shm_allocator_t *allocator, acapd_shm_t *shm) { (void)allocator; if (shm == NULL) { acapd_perror("%s: error, shm is NULL.\n", __func__); return; } if (shm->va != NULL) { free(shm->va); shm->va = NULL; shm->size = 0; } } acapd_shm_allocator_t acapd_default_shm_allocator = { .name = "shm_allocator", .priv = NULL, .alloc = acapd_generic_alloc_shm, .free = acapd_generic_free_shm, }; dfx-mgr-xilinx_v2023.2/src/sys/linux/000077500000000000000000000000001446677152000175075ustar00rootroot00000000000000dfx-mgr-xilinx_v2023.2/src/sys/linux/CMakeLists.txt000066400000000000000000000015541446677152000222540ustar00rootroot00000000000000######################################################################### # Copyright (c) 2021, Xilinx Inc. and Contributors. All rights reserved. # SPDX-License-Identifier: MIT ######################################################################### collect (PROJECT_LIB_HEADERS accel.h) collect (PROJECT_LIB_HEADERS dma.h) collect (PROJECT_LIB_HEADERS acapd-vfio-common.h) collect (PROJECT_LIB_HEADERS generic-device.h) collect (PROJECT_LIB_SOURCES accel.c) collect (PROJECT_LIB_SOURCES acapd-vfio-common.c) collect (PROJECT_LIB_SOURCES dma-axidma-vfio.c) collect (PROJECT_LIB_SOURCES dma-mcdma-vfio.c) collect (PROJECT_LIB_SOURCES device.c) collect (PROJECT_LIB_SOURCES generic-device.c) collect (PROJECT_LIB_SOURCES json-config.c) collect (PROJECT_LIB_SOURCES print.c) collect (PROJECT_LIB_SOURCES shm.c) collect (PROJECT_LIB_SOURCES shell.c) add_subdirectory (graph) dfx-mgr-xilinx_v2023.2/src/sys/linux/acapd-vfio-common.c000066400000000000000000000215331446677152000231560ustar00rootroot00000000000000/* * Copyright (c) 2021, Xilinx Inc. and Contributors. All rights reserved. * * SPDX-License-Identifier: MIT */ #include #include #include #include #include #include #include #include "acapd-vfio-common.h" #include #include #include #include "generic-device.h" #include #include #include #include #include #include #include #include #include #include #include #include #define VFIO_CONTAINER "/dev/vfio/vfio" static int acapd_vfio_bind(acapd_device_t *dev) { char tmpstr[128]; dev->bus_name = "platform"; /* Check if it is able to access sysfs */ sprintf(tmpstr, "/sys/bus/platform/drivers/vfio-platform"); if (access(tmpstr, F_OK) != 0) { acapd_debug("%s: no sysfs access, maybe in container, go ahead.\n", __func__); return 0; } return acapd_generic_device_bind(dev, "vfio-platform"); } static int acapd_vfio_device_open(acapd_device_t *dev) { struct vfio_device_info device_info = { .argsz = sizeof(device_info)}; char group_path[64]; uint32_t i; acapd_vfio_t *vdev; int ret; if (dev == NULL) { acapd_perror("%s: dev pointer is NULL.\n", __func__); return -EINVAL; } if (dev->priv != NULL) { acapd_debug("%s: dev %s already opened.\n", __func__, dev->dev_name); return 0; } /* Check if vfio device has been opened */ vdev = (acapd_vfio_t *)malloc(sizeof(*vdev)); if (vdev == NULL) { acapd_perror("%s: failed to allocate memory.\n", __func__); return -ENOMEM; } memset(vdev, 0, sizeof(*vdev)); acapd_list_init(&vdev->mmaps); snprintf(group_path, 64, "/dev/vfio/%d", dev->iommu_group); acapd_debug("%s: %s, bind vfio driver.\n", __func__, dev->dev_name); ret = acapd_vfio_bind(dev); if (ret < 0) { acapd_perror("%s: %s failed to bind driver.\n", __func__, dev->dev_name); ret = -EINVAL; goto error; } acapd_debug("%s: %s, open container.\n", __func__, dev->dev_name); vdev->container = open(VFIO_CONTAINER,O_RDWR); if (vdev->container < 0) { acapd_perror("%s: failed to open container.\n", __func__); ret = -EINVAL; goto error; } acapd_debug("%s: open group.\n", __func__); vdev->group = open(group_path, O_RDWR); if (vdev->group < 0) { acapd_perror("%s:%s failed to open group, %s.\n", __func__, dev->dev_name, strerror(errno)); ret = -EINVAL; goto error; } /* Add the group to the container */ acapd_debug("%s: add group to container.\n", __func__); ret = ioctl(vdev->group, VFIO_GROUP_SET_CONTAINER, &vdev->container); if (ret < 0) { acapd_perror("%s: %s failed to group set container ioctl:%s.\n", __func__, dev->dev_name, strerror(errno)); ret = -EINVAL; goto error; } /* Enable the IOMMU mode we want */ acapd_debug("%s: enable IOMMU mode.\n", __func__); ret = ioctl(vdev->container, VFIO_SET_IOMMU, VFIO_TYPE1_IOMMU); if (ret <0) { ret = -EINVAL; goto error; } acapd_debug("%s: get vfio device.\n", __func__); ret = ioctl(vdev->group, VFIO_GROUP_GET_DEVICE_FD, dev->dev_name); if (ret < 0) { acapd_perror("%s: Failed to get device %s, %s.\n", __func__, dev->dev_name, strerror(ret)); ret = -EINVAL; goto error; } vdev->device = ret; ret = ioctl(vdev->device, VFIO_DEVICE_GET_INFO, &device_info); if (ret < 0) { acapd_perror("%s: Failed to get %s device information:%s.\n", __func__, dev->dev_name, strerror(ret)); ret = -EINVAL; goto error; } for (i = 0; i < device_info.num_regions; i++){ struct vfio_region_info reg = { .argsz = sizeof(reg)}; reg.index = 0; ret = ioctl(vdev->device, VFIO_DEVICE_GET_REGION_INFO, ®); if (ret < 0) { acapd_perror("%s: Failed to get io of %s, %s.\n", __func__, dev->dev_name, strerror(ret)); ret = -EINVAL; goto error; } if (reg.flags & VFIO_REGION_INFO_FLAG_MMAP) { dev->va = mmap(0, reg.size, PROT_READ | PROT_WRITE, MAP_SHARED, vdev->device, reg.offset); if (dev->va == MAP_FAILED) { acapd_perror("%s:%s Failed to mmap: 0x%llx.\n", __func__, dev->dev_name, reg.offset); dev->va = NULL; ret = -EINVAL; goto error; } dev->reg_size = reg.size; } } dev->priv = vdev; return 0; error: free(vdev); return ret; } static int acapd_vfio_device_close(acapd_device_t *dev) { acapd_vfio_t *vdev; if (dev == NULL) { acapd_perror("%s: dev is NULL.\n", __func__); return -EINVAL; } vdev = (acapd_vfio_t *)dev->priv; if (vdev == NULL) { return 0; } dev->priv = NULL; while (1) { acapd_list_t *node; struct vfio_iommu_type1_dma_unmap dma_unmap = {.argsz = sizeof(dma_unmap)}; acapd_vfio_mmap_t *mmap; int ret; node = acapd_list_first(&vdev->mmaps); if (node == NULL) { break; } mmap = (acapd_vfio_mmap_t *)(acapd_container_of(node, acapd_vfio_mmap_t, node)); dma_unmap.iova = mmap->da; dma_unmap.size = mmap->size; ret = ioctl(vdev->container, VFIO_IOMMU_UNMAP_DMA, dma_unmap); if (ret < 0) { acapd_perror("%s: failed to unmap vfio memory.\n"); } acapd_list_del(&mmap->node); free(mmap); } free(vdev); return 0; } static void *acapd_vfio_device_attach(acapd_device_t *dev, acapd_shm_t *shm) { acapd_vfio_t *vdev; struct vfio_iommu_type1_dma_map dma_map = {.argsz = sizeof(dma_map)}; int ret; acapd_list_t *node; acapd_vfio_mmap_t *mmap; uint64_t da; size_t size; if (dev == NULL) { acapd_perror("%s: dev is NULL.\n", __func__); return NULL; } if (shm == NULL) { acapd_perror("%s: shm is NULL.\n", __func__); return NULL; } vdev = (acapd_vfio_t *)dev->priv; if (vdev == NULL) { acapd_perror("%s: %s vfio dev is NULL.\n", __func__, dev->dev_name); return NULL; } size = acapd_align_up(shm->size, (4 * 1024)); dma_map.size = size; dma_map.vaddr = (uint64_t)((uintptr_t)(shm->va)); dma_map.flags = VFIO_DMA_MAP_FLAG_READ | VFIO_DMA_MAP_FLAG_WRITE; /* Calculate da address */ da = 0x1000; acapd_list_for_each(&vdev->mmaps, node) { uint64_t tmp; mmap = (acapd_vfio_mmap_t *)(acapd_container_of(node, acapd_vfio_mmap_t, node)); tmp = mmap->da + mmap->size; if ((da + size) < mmap->da) { continue; } if ((da + size) <= tmp) { da = tmp; } } dma_map.iova = da; ret = ioctl(vdev->container, VFIO_IOMMU_MAP_DMA, &dma_map); if (ret) { acapd_perror("%s: Could not map DMA memory %d,%s. %p, 0x%llx, 0x%lx\n", __func__, vdev->container, strerror(ret), shm->va, da, size); return NULL; } mmap = malloc(sizeof(*mmap)); if (mmap == NULL) { acapd_perror("%s: failed to alloc memory for mmap struct.\n", __func__); return NULL; } mmap->va = shm->va; mmap->da = da; mmap->size = size; acapd_list_add_tail(&vdev->mmaps, &mmap->node); acapd_debug("%s: mmap shm done, 0x%lx, 0x%lx\n", __func__, da, size); return shm->va; } static int acapd_vfio_device_detach(acapd_device_t *dev, acapd_shm_t *shm) { acapd_vfio_t *vdev; struct vfio_iommu_type1_dma_unmap dma_unmap = {.argsz = sizeof(dma_unmap)}; int ret; acapd_list_t *node; acapd_vfio_mmap_t *mmap; if (dev == NULL) { acapd_perror("%s: dev is NULL.\n", __func__); return -EINVAL; } if (shm == NULL) { acapd_perror("%s: shm is NULL.\n", __func__); return -EINVAL; } vdev = (acapd_vfio_t *)dev->priv; if (vdev == NULL) { acapd_perror("%s: %s vfio dev is NULL.\n", __func__, dev->dev_name); return -EINVAL; } ret = -EINVAL; dma_unmap.size = shm->size; acapd_list_for_each(&vdev->mmaps, node) { mmap = (acapd_vfio_mmap_t *)(acapd_container_of(node, acapd_vfio_mmap_t, node)); if (mmap->va == shm->va) { dma_unmap.iova = mmap->da; ret = ioctl(vdev->container, VFIO_IOMMU_UNMAP_DMA, dma_unmap); if (ret < 0) { acapd_perror("%s: %s failed ioctl unmap.\n", __func__, dev->dev_name); } acapd_list_del(&mmap->node); free(mmap); break; } } return ret; } static uint64_t acapd_vfio_device_va_to_da(acapd_device_t *dev, void *va) { acapd_vfio_t *vdev; acapd_list_t *node; acapd_vfio_mmap_t *mmap; char *lva = va; if (dev == NULL) { acapd_perror("%s: dev is NULL.\n", __func__); return -EINVAL; } vdev = (acapd_vfio_t *)dev->priv; if (vdev == NULL) { acapd_perror("%s: %s vfio device is NULL.\n", __func__, dev->dev_name); return -EINVAL; } acapd_list_for_each(&vdev->mmaps, node) { mmap = (acapd_vfio_mmap_t *)(acapd_container_of(node, acapd_vfio_mmap_t, node)); if (lva >= (char *)mmap->va && lva < ((char *)mmap->va + mmap->size)) { uint64_t offset; offset = lva - (char *)mmap->va; return mmap->da + offset; } } return (uint64_t)(-1); } acapd_device_ops_t acapd_vfio_dev_ops = { .open = acapd_vfio_device_open, .close = acapd_vfio_device_close, .attach = acapd_vfio_device_attach, .detach = acapd_vfio_device_detach, .va_to_da = acapd_vfio_device_va_to_da, }; dfx-mgr-xilinx_v2023.2/src/sys/linux/acapd-vfio-common.h000066400000000000000000000014451446677152000231630ustar00rootroot00000000000000/* * Copyright (c) 2021, Xilinx Inc. and Contributors. All rights reserved. * * SPDX-License-Identifier: MIT */ /* * @file acapd-vfio-common.h */ #ifndef _ACAPD_VFIO_COMMON_H #define _ACAPD_VFIO_COMMON_H #ifdef __cplusplus extern "C" { #endif #include #include typedef struct acapd_vfio_mmap { void *va; /**< logical address */ uint64_t da; /**< device address */ size_t size; /**< size of the mmapped memory */ acapd_list_t node; /**< node */ } acapd_vfio_mmap_t; typedef struct acapd_vfio { int container; /**< vfio container fd */ int group; /**< vfio group id */ int device; /**< vfio device fd */ acapd_list_t mmaps; /**< memory maps list */ } acapd_vfio_t; extern acapd_device_ops_t acapd_vfio_dev_ops; #endif /* _ACAPD_VFIO_COMMON_H */ dfx-mgr-xilinx_v2023.2/src/sys/linux/accel.c000066400000000000000000000327351446677152000207340ustar00rootroot00000000000000/* * Copyright (c) 2021, Xilinx Inc. and Contributors. All rights reserved. * * SPDX-License-Identifier: MIT */ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "accel.h" #include #include "generic-device.h" #define MAX_BUFFERS 40 acapd_buffer_t *buffer_list = NULL; static int remove_directory(const char *path) { DIR *d = opendir(path); int r = -1; DFX_DBG("%s", path); if (d) { struct dirent *p; size_t path_len; path_len = strlen(path); r = 0; while (!r && (p=readdir(d))) { int r2 = -1; char *buf; size_t len; struct stat statbuf; /* Skip the names "." and ".." as we don't want * to recurse on them. */ if (!strcmp(p->d_name, ".") || !strcmp(p->d_name, "..")) { continue; } len = path_len + strlen(p->d_name) + 2; buf = malloc(len); if (buf == NULL) { DFX_ERR("Failed to allocate memory"); return -1; } sprintf(buf, "%s/%s", path, p->d_name); if (!stat(buf, &statbuf)) { if (S_ISDIR(statbuf.st_mode)) { r2 = remove_directory(buf); } else { r2 = unlink(buf); } } r = r2; free(buf); } closedir(d); if (r == 0) { r = rmdir(path); } } return r; } int sys_accel_config(acapd_accel_t *accel) { acapd_accel_pkg_hd_t *pkg = accel->pkg; char template[] = "/tmp/accel.XXXXXX"; char *tmp_dirname; char cmd[512]; int ret; char *env_config_path, config_path[128]; size_t len; DFX_DBG("%s", pkg ? pkg->path : ""); env_config_path = getenv("ACCEL_CONFIG_PATH"); memset(config_path, 0, sizeof(config_path)); if(env_config_path == NULL) { if(pkg->type == ACAPD_ACCEL_PKG_TYPE_TAR_GZ) { DFX_DBG("Found .tar.gz package, extracting %s", pkg->path); tmp_dirname = mkdtemp(template); if (tmp_dirname == NULL) { DFX_ERR("mkdtemp"); return ACAPD_ACCEL_FAILURE; } sprintf(accel->sys_info.tmp_dir, "%s/", tmp_dirname); sprintf(cmd, "tar -C %s -xzf %s", tmp_dirname, pkg->path); ret = system(cmd); if (ret != 0) { DFX_ERR("%s", cmd); return ACAPD_ACCEL_FAILURE; } len = sizeof(config_path) - strlen("accel.json") - 1; if (len > strlen(accel->sys_info.tmp_dir)) { len = strlen(accel->sys_info.tmp_dir); } else { DFX_ERR("path is too long: %s", tmp_dirname); return ACAPD_ACCEL_FAILURE; } } else if(pkg->type == ACAPD_ACCEL_PKG_TYPE_NONE) { DFX_DBG("No need to extract pkg %s", pkg->path); sprintf(accel->sys_info.tmp_dir, "%s/", pkg->path); len = strlen(accel->sys_info.tmp_dir); } else { DFX_ERR("unhandled package type for accel %s", pkg->path); return ACAPD_ACCEL_FAILURE; } strncpy(config_path, accel->sys_info.tmp_dir, len); strcat(config_path, "accel.json"); } else { if (sizeof(config_path) < strlen(env_config_path)) { DFX_ERR("path is too long: %s", env_config_path); return ACAPD_ACCEL_FAILURE; } strncpy(config_path, env_config_path, sizeof(config_path)); } DFX_DBG("Json Path %s", config_path); parseAccelJson(accel, config_path); if (sys_needs_load_accel(accel) == 0) { for (int i = 0; i < accel->num_ip_devs; i++) { char *tmppath; char tmpstr[32]; acapd_device_t *dev; dev = &(accel->ip_dev[i]); sprintf(tmpstr, "ACCEL_IP%d_PATH", i); tmppath = getenv(tmpstr); if (tmppath == NULL) break; if (strlen(tmppath) >= sizeof(dev->path)) { DFX_ERR("%s is too long: %s", tmpstr, tmppath); return ACAPD_ACCEL_FAILURE; } strncpy(dev->path, tmppath, sizeof(dev->path)); } } return ACAPD_ACCEL_SUCCESS; } int sys_needs_load_accel(acapd_accel_t *accel) { char *tmpstr; (void)accel; tmpstr = getenv("ACCEL_CONFIG_PATH"); DFX_DBG("ACCEL_CONFIG_PATH %s", tmpstr); if (tmpstr != NULL) { DFX_DBG("no need to load"); return 0; } else { return 1; } } int sys_fetch_accel(acapd_accel_t *accel, int flags) { int ret; DFX_DBG(""); acapd_assert(accel != NULL); ret = dfx_cfg_init(accel->sys_info.tmp_dir, 0, flags); if (ret < 0) { DFX_ERR("Failed to initialize fpga config, %d", ret); return ACAPD_ACCEL_FAILURE; } accel->sys_info.fpga_cfg_id = ret; return ACAPD_ACCEL_SUCCESS; } int sys_load_accel(acapd_accel_t *accel, unsigned int async) { int ret; int fpga_cfg_id; (void)async; DFX_DBG(""); acapd_assert(accel != NULL); if (accel->is_cached == 0) { DFX_ERR("accel is not cached."); return ACAPD_ACCEL_FAILURE; } fpga_cfg_id = accel->sys_info.fpga_cfg_id; ret = dfx_cfg_load(fpga_cfg_id); if (ret != 0) { DFX_ERR("Failed to load fpga config: %d", fpga_cfg_id); dfx_cfg_destroy(fpga_cfg_id); return ACAPD_ACCEL_FAILURE; } if ( !strcmp(accel->type,"XRT_FLAT") || !strcmp(accel->type, "PL_FLAT")) { DFX_PR("Successfully loaded base design."); return ACAPD_ACCEL_SUCCESS; } for (int i = 0; i < accel->num_ip_devs; i++) { int ret; ret = acapd_device_open(&accel->ip_dev[i]); if (ret != 0) { DFX_ERR("failed to open accel ip %s", accel->ip_dev[i].dev_name); return -EINVAL; } } return ACAPD_ACCEL_SUCCESS; } int sys_load_accel_post(acapd_accel_t *accel) { acapd_assert(accel != NULL); char cmd[512]; char tmpstr[512]; int ret; DFX_DBG(""); sprintf(cmd,"docker run --ulimit memlock=67108864:67108864 --rm -v /usr/lib:/x_usrlib -v /usr/bin/:/xbin/ -v /lib/:/xlib -v %s:%s ",accel->sys_info.tmp_dir,accel->sys_info.tmp_dir); for (int i = 0; i < accel->num_ip_devs; i++) { //int ret; char tmpstr[512]; //ret = acapd_device_open(&accel->ip_dev[i]); //if (ret != 0) { // DFX_ERR("%s: failed to open accel ip %s.\n", // __func__, accel->ip_dev[i].dev_name); // return -EINVAL; //} sprintf(tmpstr,"--device=%s:%s ",accel->ip_dev[i].path,accel->ip_dev[i].path); strcat(cmd,tmpstr); strcat(cmd,"--device=/dev/vfio:/dev/vfio "); } for (int i = 0; i < accel->num_chnls; i++) { ret = acapd_generic_device_bind(accel->chnls[i].dev, accel->chnls[i].dev->driver); if (ret != 0) { DFX_ERR("failed to open chnl dev %s", accel->chnls[i].dev->dev_name); return -EINVAL; } } sprintf(tmpstr, "%s/container.tar", accel->sys_info.tmp_dir); if (access(tmpstr, F_OK) != 0) { DFX_DBG("no need to launch container"); return 0; } sprintf(tmpstr,"docker load < %s/container.tar",accel->sys_info.tmp_dir); DFX_DBG("Loading docker container"); ret = system(tmpstr); sprintf(tmpstr," -e \"ACCEL_CONFIG_PATH=%s/accel.json\"",accel->sys_info.tmp_dir); strcat(cmd, tmpstr); strcat(cmd, " -it container"); DFX_DBG("docker run cmd: %s", cmd); ret = system(cmd); return ret; } int sys_close_accel(acapd_accel_t *accel) { DFX_DBG(""); /* Close devices and free memory */ acapd_assert(accel != NULL); for (int i = 0; i < accel->num_chnls; i++) { DFX_DBG("closing channel %d", i); acapd_dma_close(&accel->chnls[i]); } if (accel->num_chnls > 0) { free(accel->chnls[0].dev->dev_name); free(accel->chnls[0].dev); free(accel->chnls); accel->chnls = NULL; accel->num_chnls = 0; } for (int i = 0; i < accel->num_ip_devs; i++) { DFX_DBG("closing accel ip %d %s", i, accel->ip_dev[i].dev_name); acapd_device_close(&accel->ip_dev[i]); } if (accel->num_ip_devs > 0) { free(accel->ip_dev->dev_name); free(accel->ip_dev); accel->ip_dev = NULL; accel->num_ip_devs = 0; } return 0; } int sys_remove_base(int fpga_cfg_id) { int ret; DFX_DBG(""); ret = dfx_cfg_remove(fpga_cfg_id); if (ret != 0) { DFX_ERR("Failed to remove accel: %d", ret); return -1; } ret = dfx_cfg_destroy(fpga_cfg_id); if (ret != 0) { DFX_ERR("Failed to destroy accel: %d", ret); return -1; } return 0; } int sys_remove_accel(acapd_accel_t *accel, unsigned int async) { int ret, fpga_cfg_id; DFX_DBG(""); /* TODO: for now, only synchronous mode is supported */ (void)async; fpga_cfg_id = accel->sys_info.fpga_cfg_id; DFX_DBG("Removing accel %s", accel->sys_info.tmp_dir); if (accel->pkg->type == ACAPD_ACCEL_PKG_TYPE_TAR_GZ) { DFX_DBG("Removing tmp dir for .tar.gz"); ret = remove_directory(accel->sys_info.tmp_dir); if (ret != 0) { DFX_ERR("Failed to remove %s", accel->sys_info.tmp_dir); } } if (fpga_cfg_id <= 0) { DFX_ERR("Invalid fpga cfg id: %d", fpga_cfg_id); return ACAPD_ACCEL_FAILURE; } ret = dfx_cfg_remove(fpga_cfg_id); if (ret != 0) { DFX_ERR("Failed to remove accel: %d", ret); goto out; } ret = dfx_cfg_destroy(fpga_cfg_id); if (ret != 0) { DFX_ERR("Failed to destroy accel: %d", ret); goto out; } out: return ACAPD_ACCEL_SUCCESS; } int sys_send_fds(int *fds, int num_fds, int socket) { char dummy = '$'; struct msghdr msg; struct iovec iov; char cmsgbuf[CMSG_SPACE(sizeof(int)*num_fds)]; DFX_DBG(""); memset(cmsgbuf, '\0',sizeof(cmsgbuf)); int socket_d2 = accept(socket, NULL, NULL); if (socket_d2 < 0){ DFX_ERR("accept(%d, NULL, NULL)", socket); return -1; } iov.iov_base = &dummy; iov.iov_len = sizeof(dummy); msg.msg_name = NULL; msg.msg_namelen = 0; msg.msg_iov = &iov; msg.msg_iovlen = 1; msg.msg_flags = 0; msg.msg_control = cmsgbuf; msg.msg_controllen = sizeof(cmsgbuf); struct cmsghdr* cmsg = CMSG_FIRSTHDR(&msg); cmsg->cmsg_level = SOL_SOCKET; cmsg->cmsg_type = SCM_RIGHTS; cmsg->cmsg_len = CMSG_LEN(sizeof(int)*num_fds); memcpy((int*) CMSG_DATA(cmsg), fds, sizeof(int)*num_fds); int ret = sendmsg(socket_d2, &msg, 0); if (ret == -1) { DFX_ERR("send FD's failed"); return -1; } return 0; } int sys_get_fds(acapd_accel_t *accel, int slot, int socket) { int fd[2]; DFX_DBG(""); fd[0] = accel->ip_dev[2*slot].id; fd[1] = accel->ip_dev[2*slot+1].id; DFX_ERR("Daemon slot %d accel_config %d d_hls %d", slot, fd[0], fd[1]); return sys_send_fds(&fd[0], 2, socket); } void sys_get_fd(int fd, int socket) { DFX_DBG(""); sys_send_fds(&fd, 1, socket); } int sys_send_fd_pa(acapd_buffer_t *buff) { char dummy = '$'; struct msghdr msg; struct iovec iov; char cmsgbuf[CMSG_SPACE(sizeof(int))]; DFX_DBG(""); memset(cmsgbuf, '\0',sizeof(cmsgbuf)); int socket_d2 = accept(buff->socket_d, NULL, NULL); if (socket_d2 < 0){ DFX_ERR("accept(%d, NULL, NULL)", buff->socket_d); return -1; } iov.iov_base = &dummy; iov.iov_len = sizeof(dummy); msg.msg_name = NULL; msg.msg_namelen = 0; msg.msg_iov = &iov; msg.msg_iovlen = 1; msg.msg_flags = 0; msg.msg_control = cmsgbuf; msg.msg_controllen = sizeof(cmsgbuf); struct cmsghdr* cmsg = CMSG_FIRSTHDR(&msg); cmsg->cmsg_level = SOL_SOCKET; cmsg->cmsg_type = SCM_RIGHTS; cmsg->cmsg_len = CMSG_LEN(sizeof(int)); memcpy((int*) CMSG_DATA(cmsg), &buff->fd, sizeof(int)); int ret = sendmsg(socket_d2, &msg, 0); if (ret == -1) { DFX_ERR("sendmsg"); return -1; } DFX_PR("Server Sending fd %d PA %lu",buff->fd, buff->PA); ret = write(socket_d2,&buff->PA,sizeof(uint64_t)); if (ret == -1) { DFX_ERR("write. Failed to send PA for buffer"); return -1; } //close(socket_d2); return 0; } acapd_buffer_t * sys_alloc_buffer(uint64_t size) { acapd_buffer_t *buff; int i; DFX_DBG(""); if(buffer_list == NULL) { buffer_list = (acapd_buffer_t *) malloc(MAX_BUFFERS * sizeof(acapd_buffer_t)); for (i = 0; i < MAX_BUFFERS; i++) { buffer_list[i].PA = 0; } } for (i = 0; i < MAX_BUFFERS; i++) { if (!buffer_list[i].PA) { buff = &buffer_list[i]; break; } } if (i == MAX_BUFFERS){ DFX_ERR("all buffers are full"); return NULL; } buff->drm_fd = open("/dev/dri/renderD128", O_RDWR); if (buff->drm_fd < 0) { return NULL; } struct drm_zocl_create_bo bo = {size, 0xffffffff, DRM_ZOCL_BO_FLAGS_COHERENT | DRM_ZOCL_BO_FLAGS_CMA}; struct drm_gem_close closeInfo = {0, 0}; if (ioctl(buff->drm_fd, DRM_IOCTL_ZOCL_CREATE_BO, &bo) < 0) { DFX_ERR("DRM_IOCTL_ZOCL_CREATE_BO failed"); goto err1; } buff->handle = bo.handle; struct drm_zocl_info_bo boInfo = {bo.handle, 0, 0}; if (ioctl(buff->drm_fd, DRM_IOCTL_ZOCL_INFO_BO, &boInfo) < 0) { DFX_ERR("DRM_IOCTL_ZOCL_INFO_BO failed"); goto err2; } buff->PA = boInfo.paddr; buff->size = boInfo.size; DFX_PR("allocated BO size %lu paddr %lu",boInfo.size,buff->PA); struct drm_prime_handle bo_h = {bo.handle, DRM_RDWR, -1}; if (ioctl(buff->drm_fd, DRM_IOCTL_PRIME_HANDLE_TO_FD, &bo_h) < 0) { DFX_ERR("DRM_IOCTL_PRIME_HANDLE_TO_FD failed"); goto err2; } buff->fd = bo_h.fd; return buff; err2: closeInfo.handle = buff->handle; ioctl(buff->drm_fd, DRM_IOCTL_GEM_CLOSE, &closeInfo); err1: close(buff->drm_fd); return NULL; } int sys_send_buff(uint64_t size,int socket) { DFX_DBG(""); acapd_buffer_t *buff = sys_alloc_buffer(size); if (buff == NULL){ DFX_ERR("sys_alloc_buffer"); return -1; } buff->socket_d = socket; sys_send_fd_pa(buff); return 0; } int sys_free_buffer(uint64_t pa){ int i; DFX_DBG(""); for (i = 0; i < MAX_BUFFERS; i++) { if (buffer_list[i].PA == pa) { DFX_PR("Free buffer pa %lu", pa); DFX_PR("Free buffer size %lu", buffer_list[i].size); struct drm_gem_close closeInfo = {0, 0}; closeInfo.handle = buffer_list[i].handle; ioctl(buffer_list[i].drm_fd, DRM_IOCTL_GEM_CLOSE, &closeInfo); buffer_list[i].handle = -1; buffer_list[i].PA = 0; close(buffer_list[i].fd); close(buffer_list[i].drm_fd); return 0; } } DFX_ERR("No buffer allocation found for pa %lu", pa); return -1; } int sys_print_buffers(){ int i; DFX_DBG(""); for (i = 0; i < MAX_BUFFERS; i++) { DFX_PR("buffer pa %lu", buffer_list[i].PA); } return 0; } dfx-mgr-xilinx_v2023.2/src/sys/linux/accel.h000066400000000000000000000007131446677152000207300ustar00rootroot00000000000000/* * Copyright (c) 2021, Xilinx Inc. and Contributors. All rights reserved. * * SPDX-License-Identifier: MIT */ /* * @file linux/accel.h * @brief Linux specific accelerator definition. */ #ifndef _ACAPD_LINUX_ACCEL_H #define _ACAPD_LINUX_ACCEL_H #include /** * @brief accel system specific information */ typedef struct { char dtbo_dir[128]; char tmp_dir[128]; int fpga_cfg_id; } acapd_accel_sys_t; #endif /* _ACAPD_LINUX_ACCEL_H */ dfx-mgr-xilinx_v2023.2/src/sys/linux/device.c000066400000000000000000000020101446677152000211030ustar00rootroot00000000000000/* * Copyright (c) 2021, Xilinx Inc. and Contributors. All rights reserved. * * SPDX-License-Identifier: MIT */ #include #include #include #include "acapd-vfio-common.h" #include #include #include #include #include "generic-device.h" #include #include #include #include #include int sys_device_open(acapd_device_t *dev) { acapd_assert(dev != NULL); if (dev->ops != NULL && dev->ops->open != NULL) { return dev->ops->open(dev); } if (dev->ops != NULL) { return 0; } if (dev->driver == NULL) { dev->driver = "uio_pdrv_genirq"; } if (strcmp(dev->driver, "uio_pdrv_genirq") == 0) { dev->ops = &acapd_linux_generic_dev_ops; } else if (strcmp(dev->driver, "vfio-platform") == 0) { dev->ops = &acapd_vfio_dev_ops; } else { acapd_perror("%s: no ops found for device %s.\n", __func__, dev->dev_name); return -EINVAL; } return dev->ops->open(dev); } dfx-mgr-xilinx_v2023.2/src/sys/linux/dma-axidma-vfio.c000066400000000000000000000227731446677152000226310ustar00rootroot00000000000000/* * Copyright (c) 2021, Xilinx Inc. and Contributors. All rights reserved. * * SPDX-License-Identifier: MIT */ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "acapd-vfio-common.h" #define XAXIDMA_TX_OFFSET 0x00000000 /**< TX channel registers base * offset */ #define XAXIDMA_RX_OFFSET 0x00000030 /**< RX channel registers base * offset */ #define XAXIDMA_CR_OFFSET 0x00000000 /**< Channel control */ #define XAXIDMA_SR_OFFSET 0x00000004 /**< Status */ #define XAXIDMA_CDESC_OFFSET 0x00000008 /**< Current descriptor pointer */ #define XAXIDMA_CDESC_MSB_OFFSET 0x0000000C /**< Current descriptor pointer */ #define XAXIDMA_TDESC_OFFSET 0x00000010 /**< Tail descriptor pointer */ #define XAXIDMA_TDESC_MSB_OFFSET 0x00000014 /**< Tail descriptor pointer */ #define XAXIDMA_SRCADDR_OFFSET 0x00000018 /**< Simple mode source address pointer */ #define XAXIDMA_SRCADDR_MSB_OFFSET 0x0000001C /**< Simple mode source address pointer */ #define XAXIDMA_DESTADDR_OFFSET 0x00000018 /**< Simple mode destination address pointer */ #define XAXIDMA_DESTADDR_MSB_OFFSET 0x0000001C /**< Simple mode destination address pointer */ #define XAXIDMA_BUFFLEN_OFFSET 0x00000028 /**< Tail descriptor pointer */ #define XAXIDMA_SGCTL_OFFSET 0x0000002c /**< SG Control Register */ #define XAXIDMA_CR_RUNSTOP_MASK 0x00000001 /**< Start/stop DMA channel */ #define XAXIDMA_CR_RESET_MASK 0x00000004 /**< Reset DMA engine */ #define XAXIDMA_CR_KEYHOLE_MASK 0x00000008 /**< Keyhole feature */ #define XAXIDMA_CR_CYCLIC_MASK 0x00000010 /**< Cyclic Mode */ #define XAXIDMA_HALTED_MASK 0x00000001 /**< DMA channel halted */ #define XAXIDMA_IDLE_MASK 0x00000002 /**< DMA channel idle */ #define XAXIDMA_ERR_INTERNAL_MASK 0x00000010 /**< Datamover internal * err */ #define XAXIDMA_ERR_SLAVE_MASK 0x00000020 /**< Datamover slave err */ #define XAXIDMA_ERR_DECODE_MASK 0x00000040 /**< Datamover decode * err */ #define XAXIDMA_ERR_SG_INT_MASK 0x00000100 /**< SG internal err */ #define XAXIDMA_ERR_SG_SLV_MASK 0x00000200 /**< SG slave err */ #define XAXIDMA_ERR_SG_DEC_MASK 0x00000400 /**< SG decode err */ #define XAXIDMA_ERR_ALL_MASK 0x00000770 /**< All errors */ static int axidma_vfio_dma_transfer(acapd_chnl_t *chnl, acapd_dma_config_t *config) { acapd_device_t *dev; void *base_va; /**< AXI DMA reg mmaped base va address */ uint32_t v; uint64_t da; void *va; size_t size; acapd_assert(chnl != NULL); acapd_assert(chnl->dev != NULL); acapd_assert(chnl->dev->va != NULL); acapd_assert(chnl->dev->ops != NULL); acapd_assert(chnl->dev->ops->va_to_da != NULL); dev = chnl->dev; base_va = dev->va; va = config->va; size = config->size; da = dev->ops->va_to_da(dev, va); if (da == (uint64_t)(-1)) { acapd_perror("%s: failed to get da from va %p.\n", __func__, va); return -EINVAL; } if (chnl->dir == ACAPD_DMA_DEV_W) { acapd_debug("%s: data from da 0x%lx to stream.\n", __func__, da); /* write to stream, setup tx DMA */ base_va = (void *)((char *)base_va + XAXIDMA_TX_OFFSET); v = *((volatile uint32_t *)((char *)base_va + XAXIDMA_CR_OFFSET)); v |= XAXIDMA_CR_RUNSTOP_MASK; *((volatile uint32_t *)((char *)base_va + XAXIDMA_CR_OFFSET)) = v; v = *((volatile uint32_t *)((char *)base_va + XAXIDMA_SR_OFFSET)); if ((v & XAXIDMA_HALTED_MASK) != 0) { acapd_perror("%s: tx failed due to chnl is halted.\n", __func__); return -EINVAL; } *((volatile uint32_t *)((char *)base_va + XAXIDMA_SRCADDR_OFFSET)) = (uint32_t)(da & 0xFFFFFFFF); *((uint32_t *)((char *)base_va + XAXIDMA_SRCADDR_MSB_OFFSET)) = (uint32_t)((da & 0xFFFFFFFF00000000) >> 32); *((uint32_t *)((char *)base_va + XAXIDMA_BUFFLEN_OFFSET)) = size; } else { acapd_debug("%s: data from stream to da 0x%lx.\n", __func__, da); /* read from stream, setup rx DMA */ base_va = (void *)((char *)base_va + XAXIDMA_RX_OFFSET); v = *((volatile uint32_t *)((char *)base_va + XAXIDMA_CR_OFFSET)); v |= XAXIDMA_CR_RUNSTOP_MASK; *((volatile uint32_t *)((char *)base_va + XAXIDMA_CR_OFFSET)) = v; v = *((uint32_t *)((char *)base_va + XAXIDMA_SR_OFFSET)); if ((v & XAXIDMA_HALTED_MASK) != 0) { acapd_perror("%s: rx failed due to chnl is halted.\n", __func__); return -EINVAL; } *((volatile uint32_t *)((char *)base_va + XAXIDMA_DESTADDR_OFFSET)) = (uint32_t)(da & 0xFFFFFFFF); *((uint32_t *)((char *)base_va + XAXIDMA_DESTADDR_MSB_OFFSET)) = (uint32_t)((da & 0xFFFFFFFF00000000) >> 32); *((uint32_t *)((char *)base_va + XAXIDMA_BUFFLEN_OFFSET)) = size; } return size; } static int axidma_vfio_dma_stop(acapd_chnl_t *chnl) { acapd_device_t *dev; void *base_va; /**< AXI DMA reg mmaped base va address */ uint32_t v; acapd_assert(chnl != NULL); acapd_assert(chnl->dev != NULL); acapd_assert(chnl->dev->va != NULL); dev = chnl->dev; base_va = dev->va; if (chnl->dir == ACAPD_DMA_DEV_W) { /* write to stream, stop tx DMA */ base_va = (void *)((char *)base_va + XAXIDMA_TX_OFFSET); v = *((volatile uint32_t *)((char *)base_va + XAXIDMA_CR_OFFSET)); v &= (~XAXIDMA_CR_RUNSTOP_MASK); *((volatile uint32_t *)((char *)base_va + XAXIDMA_CR_OFFSET)) = v; } else { /* read from stream, stop rx DMA */ base_va = (void *)((char *)base_va + XAXIDMA_RX_OFFSET); v = *((volatile uint32_t *)((char *)base_va + XAXIDMA_CR_OFFSET)); v &= (~XAXIDMA_CR_RUNSTOP_MASK); *((volatile uint32_t *)((char *)base_va + XAXIDMA_CR_OFFSET)) = v; } return 0; } static acapd_chnl_status_t axidma_vfio_dma_poll(acapd_chnl_t *chnl) { acapd_device_t *dev; void *base_va; /**< AXI DMA reg mmaped base va address */ uint32_t v; acapd_assert(chnl != NULL); acapd_assert(chnl->dev != NULL); acapd_assert(chnl->dev->va != NULL); dev = chnl->dev; base_va = dev->va; if (chnl->dir == ACAPD_DMA_DEV_W) { /* write to stream, read tx DMA status */ base_va = (void *)((char *)base_va + XAXIDMA_TX_OFFSET); v = *((volatile uint32_t *)((char *)base_va + XAXIDMA_CR_OFFSET)); if ((v & XAXIDMA_CR_RUNSTOP_MASK) == 0) { return ACAPD_CHNL_IDLE; } v = *((volatile uint32_t *)((char *)base_va + XAXIDMA_SR_OFFSET)); if ((v & XAXIDMA_ERR_ALL_MASK) != 0) { acapd_perror("%s, tx channel of %s errors: 0x%x\n", __func__, dev->dev_name, v); return ACAPD_CHNL_ERRORS; } else if ((v & XAXIDMA_IDLE_MASK) != 0) { return ACAPD_CHNL_IDLE; } else { return ACAPD_CHNL_INPROGRESS; } } else { /* read from stream, read rx DMA status */ base_va = (void *)((char *)base_va + XAXIDMA_RX_OFFSET); v = *((volatile uint32_t *)((char *)base_va + XAXIDMA_CR_OFFSET)); if ((v & XAXIDMA_CR_RUNSTOP_MASK) == 0) { return ACAPD_CHNL_IDLE; } v = *((volatile uint32_t *)((char *)base_va + XAXIDMA_SR_OFFSET)); if ((v & XAXIDMA_ERR_ALL_MASK) != 0) { acapd_perror("%s, rx channel of %s errors: 0x%x\n", __func__, dev->dev_name, v); return ACAPD_CHNL_ERRORS; } else if ((v & XAXIDMA_IDLE_MASK) != 0) { return ACAPD_CHNL_IDLE; } else { return ACAPD_CHNL_INPROGRESS; } } } static int axidma_vfio_dma_reset(acapd_chnl_t *chnl) { acapd_device_t *dev; void *base_va; /**< AXI DMA reg mmaped base va address */ acapd_assert(chnl != NULL); acapd_assert(chnl->dev != NULL); acapd_assert(chnl->dev->va != NULL); dev = chnl->dev; base_va = dev->va; if (chnl->dir == ACAPD_DMA_DEV_W) { /* write to stream, reset tx DMA */ base_va = (void *)((char *)base_va + XAXIDMA_TX_OFFSET); *((volatile uint32_t *)((char *)base_va + XAXIDMA_CR_OFFSET)) = XAXIDMA_CR_RESET_MASK; } else { /* read from stream, reset rx DMA */ base_va = (void *)((char *)base_va + XAXIDMA_RX_OFFSET); *((volatile uint32_t *)((char *)base_va + XAXIDMA_CR_OFFSET)) = XAXIDMA_CR_RESET_MASK; } return 0; } static int axidma_vfio_dma_open(acapd_chnl_t *chnl) { acapd_device_t *dev; int ret; acapd_assert(chnl != NULL); acapd_assert(chnl->dev != NULL); dev = chnl->dev; ret = acapd_device_get(dev); if (ret < 0) { acapd_perror("%s: failed to get device %s.\n", __func__, dev->dev_name); return -EINVAL; } if (dev->refs == 1) { /* First time to open channel, reset it */ void *reg_va; /**< AXI DMA reg mmaped base va address */ uint32_t v; reg_va = dev->va; reg_va = (void *)((char *)reg_va + XAXIDMA_TX_OFFSET + XAXIDMA_CR_OFFSET); *((volatile uint32_t *)reg_va) = XAXIDMA_CR_RESET_MASK; do { v = *((volatile uint32_t *)reg_va); } while ((v & XAXIDMA_CR_RESET_MASK) != 0); } return 0; } static int axidma_vfio_dma_close(acapd_chnl_t *chnl) { acapd_device_t *dev; int ret; acapd_assert(chnl != NULL); acapd_assert(chnl->dev != NULL); dev = chnl->dev; if (dev->refs == 1) { /* last one to put device, reset it */ void *reg_va; /**< AXI DMA reg mmaped base va address */ uint32_t v; reg_va = dev->va; reg_va = (void *)((char *)reg_va + XAXIDMA_TX_OFFSET + XAXIDMA_CR_OFFSET); *((volatile uint32_t *)reg_va) = XAXIDMA_CR_RESET_MASK; do { v = *((volatile uint32_t *)reg_va); } while ((v & XAXIDMA_CR_RESET_MASK) != 0); } ret = acapd_device_put(dev); return ret; } acapd_dma_ops_t axidma_vfio_dma_ops = { .name = "axidma_vfio_dma", .transfer = axidma_vfio_dma_transfer, .stop = axidma_vfio_dma_stop, .poll = axidma_vfio_dma_poll, .reset = axidma_vfio_dma_reset, .open = axidma_vfio_dma_open, .close = axidma_vfio_dma_close, }; dfx-mgr-xilinx_v2023.2/src/sys/linux/dma-mcdma-vfio.c000066400000000000000000000252521446677152000224420ustar00rootroot00000000000000/* * Copyright (c) 2021, Xilinx Inc. and Contributors. All rights reserved. * * SPDX-License-Identifier: MIT */ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "acapd-vfio-common.h" #define MM2S_CR 0x0000 /*Control register*/ #define MM2S_SR 0x0004 /*Status register*/ #define MM2S_CHEN 0x0008 /*Channel enable/disable */ #define MM2S_CHSER 0x000C /*Channel in progress register*/ #define MM2S_ERR 0x0010 /*error register*/ #define MM2S_CH1CR 0x0040 /*CH1 control register*/ #define MM2S_CH1SR 0x0044 /*CH1 status register*/ #define MM2S_CH1CURDESC_LSB 0x0048 /*CH1 Current Descriptor (LSB)*/ #define MM2S_CH1CURDESC_MSB 0x004C /*CH1 Current Descriptor (MSB)*/ #define MM2S_CH1TAILDESC_LSB 0x0050 /*CH1 Tail Descriptor (LSB)*/ #define MM2S_CH1TAILDESC_MSB 0x0054 /*CH1 Tail Descriptor (MSB)*/ #define S2MM_CR 0x0500 /*Control register*/ #define S2MM_SR 0x0504 /*Status register*/ #define S2MM_CHEN 0x0508 /*Channel enable/disable */ #define S2MM_CHSER 0x050C /*Channel in progress register*/ #define S2MM_ERR 0x0510 /*error register*/ #define S2MM_CH1CR 0x0540 /*Ch1 control register*/ #define S2MM_CH1SR 0x0544 /*Ch1 status register*/ #define S2MM_CH1CURDESC_LSB 0x0548 /*CH1 Current Descriptor (LSB)*/ #define S2MM_CH1CURDESC_MSB 0x054C /*CH1 Current Descriptor (MSB)*/ #define S2MM_CH1TAILDESC_LSB 0x0550 /*CH1 Tail Descriptor (LSB)*/ #define S2MM_CH1TAILDESC_MSB 0x0554 /*CH1 Tail Descriptor (MSB)*/ #define MCDMA_BD_SIZE 0x40UL #define MCDMA_RUNSTOP_MASK 0x1 /*0-stop,1-run*/ #define MCDMA_CHANNELS_MASK 0x1 /*set respective bit to enable each channel*/ #define MCDMA_CHANNEL_FETCH_MASK 0x1 /*start fetch of BDs for this channel*/ #define MCDMA_IDLE_MASK 0x2 #define MCDMA_HALTED_MASK 0x1 #define MCDMA_RESET_MASK 0x4 static int mcdma_vfio_dma_transfer(acapd_chnl_t *chnl, acapd_dma_config_t *config) { acapd_device_t *dev; void *base_va; /**< AXI DMA reg mmaped base va address */ uint64_t buf_addr, bd_pa, next_bd_pa; void *va; void *bd_va; void *next_bd_va; uint32_t offset = 0x40U * chnl->chnl_id;/* chnl_id start from 0*/ acapd_shm_t bd_shm; int ret; void *retva; uint32_t buf_size, transfer_buf_size, tid; acapd_assert(chnl != NULL); acapd_assert(chnl->dev != NULL); acapd_assert(chnl->dev->va != NULL); acapd_assert(chnl->dev->ops != NULL); acapd_assert(chnl->dev->ops->va_to_da != NULL); dev = chnl->dev; base_va = dev->va; buf_size = config->size; transfer_buf_size = buf_size; va = config->va; buf_addr = dev->ops->va_to_da(dev, va); if (buf_addr == (uint64_t)(-1)) { acapd_perror("%s: failed to get Buffer da from va %p.\n", __func__, va); return -EINVAL; } memset(&bd_shm, 0, sizeof(bd_shm)); if(bd_shm.va == NULL) { ret = acapd_alloc_shm(NULL, &bd_shm, 0x1000, 0); } if (ret < 0) { acapd_perror("%s: failed to allocal BD shm memory.\n", __func__); return -EINVAL; } if (bd_shm.va == NULL) { acapd_perror("%s: BD shm va is NULL.\n", __func__); return -EINVAL; } retva = acapd_attach_shm(chnl, &bd_shm); if (retva == NULL) { acapd_perror("%s: failed to attach BD shm\n", __func__); return -EINVAL; } chnl->bd_va = bd_shm.va; bd_va = chnl->bd_va; bd_pa = dev->ops->va_to_da(dev, bd_va); if (bd_pa == (uint64_t)(-1)) { acapd_perror("%s: failed to get BD pa from va %p.\n", __func__, bd_va); return -EINVAL; } next_bd_pa = bd_pa; next_bd_va = bd_va; tid = config->tid << 24; /* Program descriptors */ for (; transfer_buf_size != 0; ) { uint32_t tmpbuf_size = transfer_buf_size; if (tmpbuf_size > chnl->max_buf_size) tmpbuf_size = chnl->max_buf_size; transfer_buf_size -= tmpbuf_size; if (transfer_buf_size != 0) next_bd_pa += MCDMA_BD_SIZE; /* Next descriptor address, desc are 64 bytes each*/ *((volatile uint32_t *)((char *)next_bd_va+0x0)) = next_bd_pa & 0xFFFFFFC0; *((volatile uint32_t *)((char *)next_bd_va+0x4)) = next_bd_pa >> 32; /* Buffer Address*/ *((volatile uint32_t *)((char *)next_bd_va+0x8)) = buf_addr & 0xFFFFFFFF; *((volatile uint32_t *)((char *)next_bd_va+0xC)) = buf_addr >> 32; /* buffer length bits 25:0| sof bit 31 | eof bit 30*/ *((volatile uint32_t *)((char *)next_bd_va+0x14)) = (tmpbuf_size & 0x3FFFFFF) | 0x80000000 | 0x40000000; /* MM2S Program the tid bits 31:24*/ if (chnl->dir == ACAPD_DMA_DEV_W) { *((volatile uint32_t *)((char *)next_bd_va+ 0x18)) = tid & 0xFF000000; } if (transfer_buf_size != 0) { next_bd_va += MCDMA_BD_SIZE; buf_addr += tmpbuf_size; } } if (chnl->dir == ACAPD_DMA_DEV_W) { uint32_t rx_status, rx_error; rx_status = *((volatile uint32_t *)((char *)base_va + S2MM_SR)); rx_error = *((volatile uint32_t *)((char *)base_va + S2MM_ERR)); if (((rx_status & MCDMA_HALTED_MASK) && (rx_error != 0)) || (rx_status & MCDMA_IDLE_MASK)) { acapd_debug("%s: MM2S Reset dma engine rx_status 0x%x rx_err 0x%x\n", __func__, rx_status, rx_error); *((volatile uint32_t *)((char *)base_va + MM2S_CR)) = MCDMA_RESET_MASK; } acapd_perror("%s: MM2S data from memory 0x%lx to stream, config->size %d, offset %d\n", __func__, buf_addr,config->size, offset); //enable the channel *((volatile uint32_t *)((char *)base_va + MM2S_CHEN)) = MCDMA_CHANNELS_MASK; /* Program Current desc */ *((volatile uint32_t *)((char *)base_va + offset + MM2S_CH1CURDESC_LSB)) = bd_pa & 0xFFFFFFC0; *((volatile uint32_t *)((char *)base_va + offset + MM2S_CH1CURDESC_MSB)) = bd_pa >> 32; //Enable fetch bit for channel *((volatile uint32_t *)((char *)base_va + offset + MM2S_CH1CR)) = MCDMA_CHANNEL_FETCH_MASK; //Run the device *((volatile uint32_t *)((char *)base_va + MM2S_CR)) = MCDMA_RUNSTOP_MASK; //program Tail desc. Each channel needs two desc-for data and control each *((volatile uint32_t *)((char *)base_va + offset + MM2S_CH1TAILDESC_LSB)) = next_bd_pa & 0xFFFFFFC0; *((volatile uint32_t *)((char *)base_va + offset + MM2S_CH1TAILDESC_MSB)) = next_bd_pa >> 32; } else { uint32_t tx_status, tx_error; tx_status = *((volatile uint32_t *)((char *)base_va + MM2S_SR)); tx_error = *((volatile uint32_t *)((char *)base_va + MM2S_ERR)); if (((tx_status & MCDMA_HALTED_MASK) && (tx_error != 0)) || (tx_status & MCDMA_IDLE_MASK)) { acapd_debug("%s: S2MM Reset dma engine tx_status 0x%x tx_err 0x%x\n", __func__, tx_status, tx_error); *((volatile uint32_t *)((char *)base_va + S2MM_CR)) = MCDMA_RESET_MASK; } acapd_perror("%s: S2MM data from stream to memory 0x%lx.\n", __func__, buf_addr); //enable the channel *((volatile uint32_t *)((char *)base_va + S2MM_CHEN)) = MCDMA_CHANNELS_MASK; *((volatile uint32_t *)((char *)base_va + offset + S2MM_CH1CURDESC_LSB)) = bd_pa & 0xFFFFFFC0; *((volatile uint32_t *)((char *)base_va + offset + S2MM_CH1CURDESC_MSB)) = bd_pa >> 32; *((volatile uint32_t *)((char *)base_va + offset + S2MM_CH1CR)) = MCDMA_CHANNEL_FETCH_MASK; *((volatile uint32_t *)((char *)base_va + S2MM_CR)) = MCDMA_RUNSTOP_MASK; /* program Tail desc. Each channel needs two desc-for data and control each*/ *((volatile uint32_t *)((char *)base_va + offset + S2MM_CH1TAILDESC_LSB)) = next_bd_pa & 0xFFFFFFC0; *((volatile uint32_t *)((char *)base_va + offset + S2MM_CH1TAILDESC_MSB)) = next_bd_pa >> 32; } return buf_size; } static int mcdma_vfio_dma_stop(acapd_chnl_t *chnl) { acapd_device_t *dev; void *base_va; /**< AXI DMA reg mmaped base va address */ uint32_t v; acapd_assert(chnl != NULL); acapd_assert(chnl->dev != NULL); acapd_assert(chnl->dev->va != NULL); dev = chnl->dev; base_va = dev->va; if (chnl->dir == ACAPD_DMA_DEV_W) { v = *((volatile uint32_t *)((char *)base_va + MM2S_CR)); v &= (~MCDMA_RUNSTOP_MASK); *((volatile uint32_t *)((char *)base_va + MM2S_CR)) = v; } else { v = *((volatile uint32_t *)((char *)base_va + S2MM_CR)); v &= (~MCDMA_RUNSTOP_MASK); *((volatile uint32_t *)((char *)base_va + S2MM_CR)) = v; } return 0; } static acapd_chnl_status_t mcdma_vfio_dma_poll(acapd_chnl_t *chnl) { acapd_device_t *dev; void *base_va; /**< AXI DMA reg mmaped base va address */ uint32_t v; acapd_assert(chnl != NULL); acapd_assert(chnl->dev != NULL); acapd_assert(chnl->dev->va != NULL); dev = chnl->dev; base_va = dev->va; if (chnl->dir == ACAPD_DMA_DEV_W) { v = *((volatile uint32_t *)((char *)base_va + MM2S_SR)); if ((v & MCDMA_HALTED_MASK) != 0) { return ACAPD_CHNL_STALLED; } else if ((v & MCDMA_IDLE_MASK) != 0) { return ACAPD_CHNL_IDLE; } else { return ACAPD_CHNL_INPROGRESS; } } else { v = *((volatile uint32_t *)((char *)base_va + S2MM_SR)); if ((v & MCDMA_HALTED_MASK) != 0) { return ACAPD_CHNL_STALLED; } else if ((v & MCDMA_IDLE_MASK) != 0) { return ACAPD_CHNL_IDLE; } else { return ACAPD_CHNL_INPROGRESS; } } } static int mcdma_vfio_dma_reset(acapd_chnl_t *chnl) { acapd_device_t *dev; void *base_va; /**< AXI DMA reg mmaped base va address */ acapd_assert(chnl != NULL); acapd_assert(chnl->dev != NULL); acapd_assert(chnl->dev->va != NULL); dev = chnl->dev; base_va = dev->va; if (chnl->dir == ACAPD_DMA_DEV_W) { *((volatile uint32_t *)((char *)base_va + MM2S_CR)) = MCDMA_RESET_MASK; } else { *((volatile uint32_t *)((char *)base_va + S2MM_CR)) = MCDMA_RESET_MASK; } return 0; } static int mcdma_vfio_dma_open(acapd_chnl_t *chnl) { acapd_device_t *dev; int ret; acapd_assert(chnl != NULL); acapd_assert(chnl->dev != NULL); dev = chnl->dev; ret = acapd_device_get(dev); if (ret < 0) { acapd_perror("%s: failed to get device %s.\n", __func__, dev->dev_name); return -EINVAL; } if (dev->refs == 1) { /* First time to open channel, reset it */ void *base_va; base_va = dev->va; *((volatile uint32_t *)((char *)base_va + MM2S_CR)) = MCDMA_RESET_MASK; sleep(1); *((volatile uint32_t *)((char *)base_va + MM2S_CR)) = 0x0; } return 0; } static int mcdma_vfio_dma_close(acapd_chnl_t *chnl) { acapd_device_t *dev; int ret; acapd_assert(chnl != NULL); acapd_assert(chnl->dev != NULL); dev = chnl->dev; if (dev->refs == 1) { /* last one to put device, reset it */ void *base_va; base_va = dev->va; *((volatile uint32_t *)((char *)base_va + MM2S_CR)) = MCDMA_RESET_MASK; sleep(1); *((volatile uint32_t *)((char *)base_va + MM2S_CR)) = 0x0; } ret = acapd_device_put(dev); return ret; } acapd_dma_ops_t mcdma_vfio_dma_ops = { .name = "mcdma_vfio_dma", .transfer = mcdma_vfio_dma_transfer, .stop = mcdma_vfio_dma_stop, .poll = mcdma_vfio_dma_poll, .reset = mcdma_vfio_dma_reset, .open = mcdma_vfio_dma_open, .close = mcdma_vfio_dma_close, }; dfx-mgr-xilinx_v2023.2/src/sys/linux/dma.h000066400000000000000000000005531446677152000204240ustar00rootroot00000000000000/* * Copyright (c) 2021, Xilinx Inc. and Contributors. All rights reserved. * * SPDX-License-Identifier: MIT */ /* * @file linux/dma.h * @brief Linux specific DMA definition. */ #ifndef _ACAPD_LINUX_DMA_H #define _ACAPD_LINUX_DMA_H extern acapd_dma_ops_t axidma_vfio_dma_ops; extern acapd_dma_ops_t mcdma_vfio_dma_ops; #endif /* _ACAPD_LINUX_DMA_H */ dfx-mgr-xilinx_v2023.2/src/sys/linux/generic-device.c000066400000000000000000000130321446677152000225230ustar00rootroot00000000000000/* * Copyright (c) 2021, Xilinx Inc. and Contributors. All rights reserved. * * SPDX-License-Identifier: MIT */ #include #include #include #include #include #include #include #include #include #include #include #include int acapd_generic_device_bind(acapd_device_t *dev, const char *drv) { char tmpstr[384]; DIR *d; struct dirent *dir; int fd; int ret; acapd_assert(dev != NULL); acapd_assert(drv != NULL); DFX_DBG("%s, %s", dev->dev_name, drv); if (dev->bus_name == NULL) { dev->bus_name = "platform"; } sprintf(tmpstr, "/sys/bus/%s/drivers", dev->bus_name); d = opendir(tmpstr); if (d == NULL) { ret = -errno; DFX_ERR("opendir(%s)", tmpstr); return ret; } while((dir = readdir(d)) != NULL) { if (dir->d_type == DT_DIR && strlen(dir->d_name) <= 64) { sprintf(tmpstr, "/sys/bus/%s/drivers/%s/%s", dev->bus_name, dir->d_name, dev->dev_name); if (access(tmpstr, F_OK) == 0) { if (strcmp(dir->d_name, drv) == 0) { DFX_DBG("dev %s already bound", dev->dev_name); ret = 0; goto out; } /* Unbind driver */ sprintf(tmpstr, "/sys/bus/%s/drivers/%s/unbind", dev->bus_name, dir->d_name); fd = open(tmpstr, O_WRONLY); if (fd < 0) { ret = -errno; DFX_ERR("open(%s)", tmpstr); goto out; } ret = write(fd, dev->dev_name, strlen(dev->dev_name) + 1); if (ret < 0) { DFX_ERR("write %s to %s", dev->dev_name, tmpstr); close(fd); goto out; } close(fd); } } } /* Bind new driver */ sprintf(tmpstr, "/sys/bus/%s/devices/%s/driver_override", dev->bus_name, dev->dev_name); fd = open(tmpstr, O_WRONLY); if (fd < 0) { ret = -errno; DFX_ERR("open(%s)", tmpstr); goto out; } ret = write(fd, drv, strlen(drv) + 1); if (ret < 0) { DFX_ERR("write %s to %s", drv, tmpstr); close(fd); goto out; } sprintf(tmpstr, "/sys/bus/%s/drivers/%s/bind", dev->bus_name, drv); fd = open(tmpstr, O_WRONLY); if (fd < 0) { ret = -errno; DFX_ERR("open(%s)", tmpstr); goto out; } ret = write(fd, dev->dev_name, strlen(dev->dev_name) + 1); if (ret < 0) { DFX_ERR("write %s to %s", dev->dev_name, tmpstr); close(fd); goto out; } close(fd); ret = 0; out: closedir(d); return ret; } static int acapd_generic_device_get_uio_path(acapd_device_t *dev) { int ret; char tmpstr[384]; DIR *d; struct dirent *dir; acapd_assert(dev != NULL); acapd_assert(dev->dev_name != NULL); sprintf(tmpstr, "/sys/bus/%s/devices/%s/uio", dev->bus_name, dev->dev_name); DFX_DBG("%s", tmpstr); d = opendir(tmpstr); if (d == NULL) { ret = -errno; DFX_ERR("opendir(%s)", tmpstr); return ret; } ret = -EINVAL; while ((dir = readdir(d)) != NULL) { if(dir->d_type == DT_DIR && !strncmp(dir->d_name, "uio", 3)) { int fd; char size_str[32], tmpname[8]; memset(dev->path, 0, sizeof(dev->path)); memset(tmpname, 0, sizeof(tmpname)); strcpy(tmpname, dir->d_name); sprintf(dev->path, "/dev/%s", tmpname); /* get io region size */ sprintf(tmpstr, "/sys/bus/%s/devices/%s/uio/%s/maps/map0/size", dev->bus_name, dev->dev_name, dir->d_name); fd = open(tmpstr, O_RDONLY); if (fd < 0) { ret = -errno; DFX_ERR("open(%s)", tmpstr); goto out; } memset(size_str, 0, sizeof(size_str)); ret = read(fd, size_str, sizeof(size_str)); if (ret < 0) { DFX_ERR("read(%s)", tmpstr); close(fd); goto out; } dev->reg_size = strtoull(size_str, NULL, 16); DFX_DBG("%s = %#lx", tmpstr, dev->reg_size); close(fd); ret = 0; goto out; } } out: closedir(d); return ret; } static int acapd_generic_device_open(acapd_device_t *dev) { int ret; acapd_assert(dev != NULL); DFX_DBG("%p %s", dev, dev->dev_name); if (dev->va != NULL && dev->priv != NULL) { /* Device is already open */ return 0; } if (dev->bus_name == NULL) { dev->bus_name = "platform"; } if (strlen(dev->path) == 0 || access(dev->path, F_OK) != 0) { if (dev->dev_name != NULL) { ret = acapd_generic_device_bind(dev, "uio_pdrv_genirq"); if (ret < 0) { DFX_ERR("device_bind %s", dev->dev_name); return -EINVAL; } ret = acapd_generic_device_get_uio_path(dev); if (ret < 0) { DFX_ERR("get_uio_path %s", dev->dev_name); return -EINVAL; } } else { DFX_ERR("no dev name or path is specified"); return -EINVAL; } } if (strlen(dev->path) != 0 && access(dev->path, F_OK) == 0) { int fd; fd = open(dev->path, O_RDWR); if (fd < 0) { DFX_ERR("open(%s) for %s", dev->path, dev->dev_name); return -EINVAL; } if (dev->reg_size == 0) { DFX_ERR("failed to get %s,%s size; reg_siz is 0", dev->dev_name, dev->path); close(fd); return -EINVAL; } dev->va = mmap(NULL, dev->reg_size, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0); if (dev->va == MAP_FAILED) { DFX_ERR("mmap %s, 0x%lx", dev->path, dev->reg_size); dev->va = NULL; close(fd); return -EINVAL; } dev->id = fd; DFX_DBG("fd, mmap(%s) = %d, %p ", dev->dev_name, fd, dev->va); } else { DFX_ERR("failed to access path %s", dev->path); return -EINVAL; } return 0; } static int acapd_generic_device_close(acapd_device_t *dev) { acapd_assert(dev != NULL); DFX_DBG("%s", dev->dev_name); if (dev->va == NULL) { return 0; } dev->va = NULL; close(dev->id); return 0; } acapd_device_ops_t acapd_linux_generic_dev_ops = { .open = acapd_generic_device_open, .close = acapd_generic_device_close, .attach = NULL, .detach = NULL, .va_to_da = NULL, }; dfx-mgr-xilinx_v2023.2/src/sys/linux/generic-device.h000066400000000000000000000007271446677152000225370ustar00rootroot00000000000000/* * Copyright (c) 2021, Xilinx Inc. and Contributors. All rights reserved. * * SPDX-License-Identifier: MIT */ /* * @file acapd-vfio-common.h */ #ifndef _ACAPD_LINUX_GENERIC_DEVICE_H #define _ACAPD_LINUX_GENERIC_DEVICE_H #ifdef __cplusplus extern "C" { #endif #include extern acapd_device_ops_t acapd_linux_generic_dev_ops; int acapd_generic_device_bind(acapd_device_t *dev, const char *drv); #endif /* _ACAPD_LINUX_GENERIC_DEVICE_H */ dfx-mgr-xilinx_v2023.2/src/sys/linux/graph/000077500000000000000000000000001446677152000206105ustar00rootroot00000000000000dfx-mgr-xilinx_v2023.2/src/sys/linux/graph/CMakeLists.txt000066400000000000000000000016371446677152000233570ustar00rootroot00000000000000add_subdirectory (layer0) collect (PROJECT_LIB_HEADERS abstractGraph.h) collect (PROJECT_LIB_HEADERS graph.h) collect (PROJECT_LIB_HEADERS metadata.h) collect (PROJECT_LIB_HEADERS scheduler.h) collect (PROJECT_LIB_HEADERS jobScheduler.h) collect (PROJECT_LIB_HEADERS aes128.h) collect (PROJECT_LIB_HEADERS aes192.h) collect (PROJECT_LIB_HEADERS aesFallback.h) collect (PROJECT_LIB_HEADERS aes192Fallback.h) #collect (PROJECT_LIB_HEADERS schedulerBypass.h) collect (PROJECT_LIB_SOURCES abstractGraph.c) collect (PROJECT_LIB_SOURCES graph.c) collect (PROJECT_LIB_SOURCES metadata.c) #collect (PROJECT_LIB_SOURCES main.c) collect (PROJECT_LIB_SOURCES scheduler.c) collect (PROJECT_LIB_SOURCES jobScheduler.c) collect (PROJECT_LIB_SOURCES aes128.c) collect (PROJECT_LIB_SOURCES aes192.c) collect (PROJECT_LIB_SOURCES aesFallback.c) collect (PROJECT_LIB_SOURCES aes192Fallback.c) #collect (PROJECT_LIB_SOURCES schedulerBypass.c) dfx-mgr-xilinx_v2023.2/src/sys/linux/graph/abstractGraph.c000066400000000000000000000435311446677152000235470ustar00rootroot00000000000000/* * Copyright (c) 2021, Xilinx Inc. and Contributors. All rights reserved. * * SPDX-License-Identifier: MIT */ #include #include #include #include #include #include #include #include #include "jobScheduler.h" #include "abstractGraph.h" #include "graph.h" #include "metadata.h" int softgFFT(void** inData, int* inDataSize, void** outData, int* outDataSize){ INFO("FALLBACK CALLED !!\n"); _unused(outDataSize); memcpy(outData[0], inData[0], inDataSize[0]); return 0; } int softgFIR(void** inData, int* inDataSize, void** outData, int* outDataSize){ INFO("FALLBACK CALLED !!\n"); _unused(outDataSize); memcpy(outData[0], inData[0], inDataSize[0]); return 0; } Element_t* addElement(Element_t** headElement, Element_t* nextElement){ Element_t *head = *headElement; if(head != NULL){ while(head->tail != NULL){ head = head->tail; } head->tail = nextElement; nextElement->head = head; } else{ *headElement = nextElement; } return nextElement; } int delElement(Element_t** elementList, Element_t* element){ Element_t *headElement = element->head; Element_t *tailElement = element->tail; if(headElement != NULL){ headElement->tail = element; }else{ *elementList = tailElement; } if(tailElement != NULL){ tailElement->head = headElement; } free(element); element = NULL; return 0; } AbstractGraph_t* graphInit(){//uint8_t schedulerBypassFlag){ srand(time(NULL)); AbstractGraph_t * graph = malloc(sizeof(AbstractGraph_t)); graph->id = rand(); graph->type = ENABLE_SCHEDULER; graph->accelNodeHead = NULL; graph->buffNodeHead = NULL; graph->linkHead = NULL; graph->accelNodeID = 0; graph->buffNodeID = 0; graph->linkID = 0; graph->accelCount = 0; return graph; } //int graphFinalise(AcapGraph_t *acapGraph){ // acapGraphFinalise(acapGraph); // return 0; //} int graphFinalise(AbstractGraph_t *graph){ //acapGraphFinalise(acapGraph); free(graph); return 0; } /*AccelNode_t* addInputNode(AcapGraph_t *acapGraph, uint8_t *buff, int size, int SchedulerBypassFlag){ return acapAddInputNode(acapGraph, buff, size, SchedulerBypassFlag); } AccelNode_t* addOutputNode(AcapGraph_t *acapGraph, uint8_t *buff, int size, int SchedulerBypassFlag){ return acapAddOutputNode(acapGraph, buff, size, SchedulerBypassFlag); } AccelNode_t* addAcceleratorNode(AcapGraph_t *acapGraph, char *name, int SchedulerBypassFlag){ Json_t* json = malloc(sizeof(Json_t)); Metadata_t *metadata = malloc(sizeof(Metadata_t)); char jsonfile[100]; #if 1 if(strcmp(name, "FFT4")){ strcpy(jsonfile, "/media/test/home/root/accel.json"); } else if(strcmp(name, "aes128encdec")){ strcpy(jsonfile, "/media/test/home/root/accel.json"); } else if(strcmp(name, "fir_compiler")){ strcpy(jsonfile, "/media/test/home/root/accel.json"); } #else if(strcmp(name, "FFT4")){ strcpy(jsonfile, "/media/test/home/root/accelInterrm.json"); } else if(strcmp(name, "aes128encdec")){ strcpy(jsonfile, "/media/test/home/root/accelInterrm.json"); } else if(strcmp(name, "fir_compiler")){ strcpy(jsonfile, "/media/test/home/root/accelInterrm.json"); } #endif file2json(jsonfile, json); json2meta(json, metadata); printMeta(metadata); return acapAddAccelNode(acapGraph, name, metadata->DMA_type, NULL, //metadata->fallback.lib, metadata->interRM.compatible, SchedulerBypassFlag); } BuffNode_t* addBuffer(AcapGraph_t *acapGraph, int size, int type){ return acapAddBuffNode(acapGraph, size, "buffer", type); } Link_t *addOutBuffer(AcapGraph_t *acapGraph, AccelNode_t *accelNode, BuffNode_t *buffNode, int offset, int transactionSize, int transactionIndex, int channel){ return acapAddOutputBuffer(acapGraph, accelNode, buffNode, offset, transactionSize, transactionIndex, channel); } Link_t *addInBuffer(AcapGraph_t *acapGraph, AccelNode_t *accelNode, BuffNode_t *buffNode, int offset, int transactionSize, int transactionIndex, int channel){ return acapAddInputBuffer(acapGraph, accelNode, buffNode, offset, transactionSize, transactionIndex, channel); } */ //Link_t *addInputBuffer(AcapGraph_t *acapGraph, AccelNode_t *accelNode, BuffNode_t *buffNode, // int transactionSize, int transactionIndex, int channel){ // return acapAddInputBuffer(AcapGraph_t *acapGraph, AccelNode_t *accelNode, BuffNode_t *buffNode, // int transactionSize, int transactionIndex, int channel); //} AbstractAccelNode_t* createNode(uint32_t id, uint32_t type, uint32_t size, char* name){ AbstractAccelNode_t *node = (AbstractAccelNode_t *) malloc(sizeof(AbstractAccelNode_t)); node->id = id; node->type = type; strcpy(node->name, name); node->size = size; node->semaphore = rand(); return node; } int printAccelNode(AbstractAccelNode_t *node, char * json){ //printf("%p\n", node); //printf("type: %d\n", node->type); //printf("name: %s\n", node->name); //printf("size: %d\n", node->size); return sprintf(json, "{\"id\": %d, \"type\": %d, \"name\": \"%s\", \"size\": %d, \"semaphore\": %d}", node->id, node->type, node->name, node->size, node->semaphore); } AbstractBuffNode_t* createBNode(uint32_t id, uint32_t type, uint32_t size, char* name){ AbstractBuffNode_t *node = (AbstractBuffNode_t *) malloc(sizeof(AbstractBuffNode_t)); node->id = id; node->type = type; strcpy(node->name, name); node->size = size; return node; } int printBuffNode(AbstractBuffNode_t *node, char * json){ //printf("type: %d, name: %s, size: %d\n", node->type, node->name, node->size); return sprintf(json, "{\"id\": %d, \"type\": %d, \"name\": \"%s\", \"size\": %d}", node->id, node->type, node->name, node->size); } AbstractLink_t* createLink(AbstractAccelNode_t *accelNode, AbstractBuffNode_t *buffNode, uint32_t id, uint8_t type, uint32_t offset, uint32_t transactionSize, uint8_t transactionIndex, uint8_t channel){ AbstractLink_t *node = (AbstractLink_t *) malloc(sizeof(AbstractLink_t)); node->id = id; node->accelNode = accelNode; node->buffNode = buffNode; node->type = type; node->transactionIndex = transactionIndex; node->transactionSize = transactionSize; node->offset = offset; node->channel = channel; return node; } int printLink(AbstractLink_t *node, char * json){ return sprintf(json, "{\"id\": %d, \"accelNode\": %d, \"buffNode\": %d, \"type\": %d, \"transactionIndex\": %d, \"transactionSize\": %d, \"offset\": %d, \"channel\": %d}", node->id, node->accelNode->id, node->buffNode->id, node->type, node->transactionIndex, node->transactionSize, node->offset, node->channel); } AbstractAccelNode_t* addInputNode(AbstractGraph_t *graph, int size){ Element_t* element = (Element_t *) malloc(sizeof(Element_t)); element->node = createNode(graph->accelNodeID, IN_NODE, size, "Input"); graph->accelNodeID ++; element->head = NULL; element->tail = NULL; addElement(&(graph->accelNodeHead), element); return element->node; } AbstractAccelNode_t* addOutputNode(AbstractGraph_t *graph, int size){ Element_t* element = (Element_t *) malloc(sizeof(Element_t)); element->node = createNode(graph->accelNodeID, OUT_NODE, size, "Output"); graph->accelNodeID ++; element->head = NULL; element->tail = NULL; addElement(&(graph->accelNodeHead), element); return element->node; } AbstractAccelNode_t* addAcceleratorNode(AbstractGraph_t *graph, char *name){ Element_t* element = (Element_t *) malloc(sizeof(Element_t)); element->node = createNode(graph->accelNodeID, HW_NODE, 0, name); graph->accelNodeID ++; graph->accelCount ++; element->head = NULL; element->tail = NULL; addElement(&(graph->accelNodeHead), element); return element->node; } AbstractBuffNode_t* addBuffer(AbstractGraph_t *graph, int size, int type){ Element_t* element = (Element_t *) malloc(sizeof(Element_t)); element->node = createBNode(graph->buffNodeID, type, size, "Buffer"); graph->buffNodeID ++; element->head = NULL; element->tail = NULL; addElement(&(graph->buffNodeHead), element); return element->node; } AbstractLink_t *addOutBuffer(AbstractGraph_t *graph, AbstractAccelNode_t *accelNode, AbstractBuffNode_t *buffNode, uint32_t offset, uint32_t transactionSize, uint8_t transactionIndex, uint8_t channel){ Element_t* element = (Element_t *) malloc(sizeof(Element_t)); element->node = createLink(accelNode, buffNode, graph->linkID, 1, offset, transactionSize, transactionIndex, channel); graph->linkID ++; element->head = NULL; element->tail = NULL; addElement(&(graph->linkHead), element); return element->node; } AbstractLink_t *addInBuffer(AbstractGraph_t *graph, AbstractAccelNode_t *accelNode, AbstractBuffNode_t *buffNode, uint32_t offset, uint32_t transactionSize, uint8_t transactionIndex, uint8_t channel){ Element_t* element = (Element_t *) malloc(sizeof(Element_t)); element->node = createLink(accelNode, buffNode, graph->linkID, 0, offset, transactionSize, transactionIndex, channel); graph->linkID ++; element->head = NULL; element->tail = NULL; addElement(&(graph->linkHead), element); return element->node; } int abstractGraph2Json(AbstractGraph_t *graph, char* json){ int len = 0; uint32_t id = graph->id; uint8_t type = graph->type; Element_t *accelNodeHead = graph->accelNodeHead, *accelNode; Element_t *buffNodeHead = graph->buffNodeHead, *buffNode; Element_t *linkHead = graph->linkHead, *link; len += sprintf(json + len, "{\"id\": %d, \"type\": %x,\n", id, type); accelNode = accelNodeHead; len += sprintf(json + len, "\"accelNode\": [\n"); while(accelNode != NULL){ len += printAccelNode(accelNode->node, json + len); if(accelNode->tail){ len += sprintf(json + len, ",\n"); } accelNode = accelNode->tail; } len += sprintf(json + len, "],\n"); buffNode = buffNodeHead; len += sprintf(json + len, "\"buffNode\": [\n"); while(buffNode != NULL){ len += printBuffNode(buffNode->node, json + len); if(buffNode->tail){ len += sprintf(json + len, ",\n"); } buffNode = buffNode->tail; } len += sprintf(json + len, "],\n"); link = linkHead; len += sprintf(json + len, "\"links\": [\n"); while(link != NULL){ len += printLink(link->node, json + len); if(link->tail){ len += sprintf(json + len, ",\n"); } link = link->tail; } len += sprintf(json + len, "]\n"); len += sprintf(json + len, "}\n"); printf("%s\n", json); return len; } int abstractGraphConfig(AbstractGraph_t *graph){ char json[1024*32]; int len; int fd[25]; int fdcount = 0; int status; graph->gs = malloc(sizeof(socket_t)); INFO("\n"); len = abstractGraph2Json(graph, json); INFO("\n"); status = initSocket(graph->gs); INFO("\n"); if(status < 0){ return -1; } //INFO("\n"); // INFO("@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@\n"); status = graphClientSubmit(graph->gs, json, len, fd, &fdcount); if (status < 0){ return -1; } //INFO("@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@\n"); //for(int i = 0; i < fdcount; i++){ // INFO("%d\n",fd[i]); //} reallocateIOBuffers(graph, fd, fdcount); return 0; } int abstractGraphFinalise(AbstractGraph_t *graph){ char json[1024*4]; int len; //len = abstractGraph2Json(graph, json); memset(json, '\0', 1024*4); len = sprintf(json, "{\"id\": %d}", graph->id); //INFO("%d %s\n", len, json); graphClientFinalise(graph->gs, json, len); appFinaliseIPBuffers(graph); //printf("abstractGraphFinalise\n"); while(graph->linkHead != NULL){ free((AbstractLink_t *)graph->linkHead->node); graph->linkHead->node = NULL; delElement(&(graph->linkHead), graph->linkHead); } while(graph->buffNodeHead != NULL){ free((AbstractBuffNode_t *)graph->buffNodeHead->node); graph->buffNodeHead->node = NULL; delElement(&(graph->buffNodeHead), graph->buffNodeHead); } while(graph->accelNodeHead != NULL){ free((AbstractAccelNode_t *)graph->accelNodeHead->node); graph->accelNodeHead->node = NULL; delElement(&(graph->accelNodeHead), graph->accelNodeHead); } free(graph); return 0; } int appFinaliseIPBuffers(AbstractGraph_t *graph){ Element_t *element = graph->accelNodeHead; while (element != NULL){ AbstractAccelNode_t *node = element->node; if(node->type == IN_NODE || node->type == OUT_NODE){ char SemaphoreName[100]; memset(SemaphoreName, '\0', 100); sprintf(SemaphoreName, "%d", node->semaphore); sem_close(node->semptr); sem_unlink(SemaphoreName); node->semptr = NULL; //INFO("unmapBuffer fd : %d size: %d ptr: %p\n", node->fd, node->size, &node->ptr); unmapBuffer(node->fd, node->size, &node->ptr); } element = element->tail; } return 0; } int reallocateIOBuffers(AbstractGraph_t *graph, int* fd, int fdcount){ int i = 0; _unused(fdcount); Element_t *element = graph->accelNodeHead; while (element != NULL){ AbstractAccelNode_t *node = element->node; if(node->type == IN_NODE || node->type == OUT_NODE){ node->fd = fd[i]; mapBuffer(node->fd, node->size, &node->ptr); i ++; //INFO("%p\n", node); //INFO("node->fd = %d\n", node->fd); //INFO("node->size = %d\n", node->size); //INFO("node->ptr = %p\n", node->ptr); //INFO("node->semaphore = %d\n", node->semaphore); char SemaphoreName[100]; memset(SemaphoreName, '\0', 100); sprintf(SemaphoreName, "%d", node->semaphore); //INFO("%s\n", SemaphoreName); node->semptr = sem_open(SemaphoreName, /* name */ O_CREAT, /* create the semaphore */ S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH, /* protection perms */ 0); /* initial value */ if (node->semptr == ((void*) -1)){ INFO("sem_open\n"); } } element = element->tail; } return 0; } int allocateIOBuffers(AbstractGraph_t *graph, int* fd){ int status; //INFO("graph ID: %d\n", graph->id); int fdcnt = 0; if(!graph->xrt_fd){ graph->xrt_fd = open("/dev/dri/renderD128", O_RDWR); if (graph->xrt_fd < 0) { return -1; } } Element_t *element = graph->accelNodeHead; while (element != NULL){ AbstractAccelNode_t *node = element->node; if(node->type == IN_NODE || node->type == OUT_NODE){ status = xrt_allocateBuffer(graph->xrt_fd, node->size, &node->handle, &node->ptr, &node->phyAddr, &node->fd); if(status < 0){ printf( "error @ config allocation\n"); return status; } char SemaphoreName[100]; memset(SemaphoreName, '\0', 100); sprintf(SemaphoreName, "%d", node->semaphore); //INFO("%s\n", SemaphoreName); node->semptr = sem_open(SemaphoreName, /* name */ O_CREAT, /* create the semaphore */ S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH, /* protection perms */ 0); /* initial value */ if (node->semptr == ((void*) -1)){ INFO("sem_open\n"); } fd[fdcnt] = node->fd; fdcnt ++; //INFO("io allocated : size = %d handle = %d ptr = %p paddr = %lx\n", // node->size, node->handle, node->ptr, node->phyAddr); } element = element->tail; } return fdcnt; } int deallocateIOBuffers(AbstractGraph_t *graph){ int status; //INFO("graph ID: %d\n", graph->id); Element_t *element = graph->accelNodeHead; while (element != NULL){ AbstractAccelNode_t *node = element->node; if(node->type == IN_NODE || node->type == OUT_NODE){ char SemaphoreName[100]; memset(SemaphoreName, '\0', 100); sprintf(SemaphoreName, "%d", node->semaphore); sem_close(node->semptr); sem_unlink(SemaphoreName); node->semptr = NULL; // INFO("unmapBuffer fd : %d size: %d ptr: %p\n", node->fd, node->size, &node->ptr); unmapBuffer(node->fd, node->size, &node->ptr); status = xrt_deallocateBuffer(graph->xrt_fd, node->size, &node->handle, &node->ptr, &node->phyAddr); if(status < 0){ printf( "error @ config deallocation\n"); return status; } //INFO("io deallocated"); } element = element->tail; } return 0; } int abstractGraphServerConfig(JobScheduler_t *scheduler, char* json, int len, int* fd){ char json2[1024*32]; _unused(len); int status; int fdcnt; //INFO("%s\n", json); //INFO("%p\n", scheduler->graphList); AbstractGraph_t *graph = malloc(sizeof(AbstractGraph_t)); Element_t* element = (Element_t *) malloc(sizeof(Element_t)); status = graphParser(json, &graph); if(status == 1){ INFO("Error Occured !!"); return 1; } //INFO("\n"); graph->state = AGRAPH_PREINIT; abstractGraph2Json(graph, json2); fdcnt = allocateIOBuffers(graph, fd); //INFO("\n"); element->node = graph; element->head = NULL; element->tail = NULL; //INFO("%p\n", scheduler->graphList); if(scheduler->graphList == NULL){ scheduler->graphList = element; } else{ addElement(&(scheduler->graphList), element); } //INFO("\n"); jobSchedulerSubmit(scheduler, element); graph->state = AGRAPH_INIT; return fdcnt; } Element_t *searchGraphById(Element_t **GraphList, uint32_t id){ Element_t *graphElement = *GraphList; Element_t * graph = NULL; while(1){ if(id == ((AbstractGraph_t *)graphElement->node)->id){ graph = graphElement; break; } if(graphElement->tail){ graphElement = graphElement->tail; } else break; } return graph; } int abstractGraphServerFinalise(JobScheduler_t *scheduler, char* json){ int id = graphIDParser(json); Element_t *graphNode = searchGraphById(&(scheduler->graphList), id); jobSchedulerRemove(scheduler, graphNode); AbstractGraph_t *graph = (AbstractGraph_t *)graphNode->node; printf("abstractGraphFinalise\n"); deallocateIOBuffers(graph); printf("abstractGraphFinalise\n"); while(graph->linkHead != NULL){ free((AbstractLink_t *)graph->linkHead->node); graph->linkHead->node = NULL; delElement(&(graph->linkHead), graph->linkHead); } while(graph->buffNodeHead != NULL){ free((AbstractBuffNode_t *)graph->buffNodeHead->node); graph->buffNodeHead->node = NULL; delElement(&(graph->buffNodeHead), graph->buffNodeHead); } while(graph->accelNodeHead != NULL){ free((AbstractAccelNode_t *)graph->accelNodeHead->node); graph->accelNodeHead->node = NULL; delElement(&(graph->accelNodeHead), graph->accelNodeHead); } free(graph); graph = NULL; //INFO("%p %p\n", graphNode->head, graphNode->tail); delElement(&(scheduler->graphList), graphNode); return 0; } int Data2IO(AbstractAccelNode_t *node, uint8_t *ptr, int size){ memcpy(node->ptr, ptr, size); sem_post(node->semptr); return 0; } int IO2Data(AbstractAccelNode_t *node, uint8_t *ptr, int size){ sem_wait(node->semptr); memcpy(ptr, node->ptr, size); return 0; } dfx-mgr-xilinx_v2023.2/src/sys/linux/graph/abstractGraph.h000066400000000000000000000067301446677152000235540ustar00rootroot00000000000000/* * Copyright (c) 2021, Xilinx Inc. and Contributors. All rights reserved. * * SPDX-License-Identifier: MIT */ #include #include #define AGRAPH_INIT 0XC0 #define AGRAPH_SCHEDULED 0XC1 #define AGRAPH_EXECUTING 0XC2 #define AGRAPH_COMPLETED 0XC3 #define AGRAPH_PREINIT 0XC4 typedef struct AbstractBuffNode AbstractBuffNode_t; typedef struct AbstractAccelNode AbstractAccelNode_t; typedef struct AbstractLink AbstractLink_t; typedef struct AbstractGraph AbstractGraph_t; typedef struct Element Element_t; typedef struct AccelNode AccelNode_t; typedef struct BuffNode BuffNode_t; typedef struct Link Link_t; typedef struct JobScheduler JobScheduler_t; struct Element{ void* node; struct Element *head; struct Element *tail; }; struct AbstractAccelNode{ uint8_t type; char name[256]; uint32_t size; uint32_t id; int fd; // File descriptor from ACAPD int handle; // Buffer XRT Handeler uint8_t* ptr; // Buffer Ptr unsigned long phyAddr; // Buffer Physical Address uint32_t semaphore; sem_t* semptr; AccelNode_t *node; //int SchedulerBypassFlag; }; struct AbstractBuffNode{ uint8_t type; char name[256]; uint32_t size; uint32_t id; BuffNode_t *node; }; struct AbstractLink{ AbstractAccelNode_t *accelNode;// Reference to connected accelerator AbstractBuffNode_t *buffNode;// Reference to connected buffer uint8_t type; uint8_t transactionIndex; uint32_t transactionSize; uint32_t offset; uint8_t channel; uint32_t id; Link_t *node; }; struct AbstractGraph{ uint32_t id; uint8_t type; uint8_t state; uint32_t accelCount; socket_t *gs; int xrt_fd; Element_t *accelNodeHead; Element_t *buffNodeHead; Element_t *linkHead; uint32_t accelNodeID; uint32_t buffNodeID; uint32_t linkID; }; //extern AcapGraph_t* graphInit(); //extern int graphFinalise(AcapGraph_t *acapGraph); extern AbstractGraph_t* graphInit(); //uint8_t schedulerBypassFlag); extern int graphFinalise(AbstractGraph_t *graph); extern AbstractAccelNode_t* addInputNode(AbstractGraph_t *graph, int size); extern AbstractAccelNode_t* addOutputNode(AbstractGraph_t *graph, int size); extern AbstractAccelNode_t* addAcceleratorNode(AbstractGraph_t *graph, char *name); extern AbstractBuffNode_t* addBuffer(AbstractGraph_t *graph, int size, int type); extern AbstractLink_t *addOutBuffer(AbstractGraph_t *graph, AbstractAccelNode_t *accelNode, AbstractBuffNode_t *buffNode, uint32_t offset, uint32_t transactionSize, uint8_t transactionIndex, uint8_t channel); extern AbstractLink_t *addInBuffer(AbstractGraph_t *graph, AbstractAccelNode_t *accelNode, AbstractBuffNode_t *buffNode, uint32_t offset, uint32_t transactionSize, uint8_t transactionIndex, uint8_t channel); extern int abstractGraph2Json(AbstractGraph_t *graph, char* json); extern int abstractGraphConfig(AbstractGraph_t *graph); extern int abstractGraphFinalise(AbstractGraph_t *graph); extern Element_t* addElement(Element_t** headElement, Element_t* nextElement); extern Element_t *searchGraphById(Element_t** headElement, uint32_t id); extern int abstractGraphServerConfig(JobScheduler_t *scheduler, char* json, int len, int* fd); extern int abstractGraphServerFinalise(JobScheduler_t *scheduler, char* json); extern int reallocateIOBuffers(AbstractGraph_t *graph, int* fd, int fdcount); extern int appFinaliseIPBuffers(AbstractGraph_t *graph); extern int softgFFT(void** inData, int* inDataSize, void** outData, int* outDataSize); extern int softgFIR(void** inData, int* inDataSize, void** outData, int* outDataSize); dfx-mgr-xilinx_v2023.2/src/sys/linux/graph/aes128.c000066400000000000000000000443371446677152000217720ustar00rootroot00000000000000/* This is an implementation of the AES algorithm, specifically ECB, CTR and CBC mode. Block size can be chosen in aes.h - available choices are AES128, AES192, AES256. The implementation is verified against the test vectors in: National Institute of Standards and Technology Special Publication 800-38A 2001 ED ECB-AES128 ---------- plain-text: 6bc1bee22e409f96e93d7e117393172a ae2d8a571e03ac9c9eb76fac45af8e51 30c81c46a35ce411e5fbc1191a0a52ef f69f2445df4f9b17ad2b417be66c3710 key: 2b7e151628aed2a6abf7158809cf4f3c resulting cipher 3ad77bb40d7a3660a89ecaf32466ef97 f5d3d58503b9699de785895a96fdbaaf 43b1cd7f598ece23881b00e3ed030688 7b0c785e27e8ad3f8223207104725dd4 NOTE: String length must be evenly divisible by 16byte (str_len % 16 == 0) You should pad the end of the string with zeros if this is not the case. For AES192/256 the key size is proportionally larger. */ /*****************************************************************************/ /* Includes: */ /*****************************************************************************/ #include #include // CBC mode, for memset #include "aes128.h" /*****************************************************************************/ /* Defines: */ /*****************************************************************************/ // The number of columns comprising a state in AES. This is a constant in AES. Value=4 #define Nb 4 #if defined(AES256) && (AES256 == 1) #define Nk 8 #define Nr 14 #elif defined(AES192) && (AES192 == 1) #define Nk 6 #define Nr 12 #else #define Nk 4 // The number of 32 bit words in a key. #define Nr 10 // The number of rounds in AES Cipher. #endif // jcallan@github points out that declaring Multiply as a function // reduces code size considerably with the Keil ARM compiler. // See this link for more information: https://github.com/kokke/tiny-AES-C/pull/3 #ifndef MULTIPLY_AS_A_FUNCTION #define MULTIPLY_AS_A_FUNCTION 0 #endif /*****************************************************************************/ /* Private variables: */ /*****************************************************************************/ // state - array holding the intermediate results during decryption. typedef uint8_t state_t[4][4]; // The lookup-tables are marked const so they can be placed in read-only storage instead of RAM // The numbers below can be computed dynamically trading ROM for RAM - // This can be useful in (embedded) bootloader applications, where ROM is often limited. static const uint8_t sbox[256] = { //0 1 2 3 4 5 6 7 8 9 A B C D E F 0x63, 0x7c, 0x77, 0x7b, 0xf2, 0x6b, 0x6f, 0xc5, 0x30, 0x01, 0x67, 0x2b, 0xfe, 0xd7, 0xab, 0x76, 0xca, 0x82, 0xc9, 0x7d, 0xfa, 0x59, 0x47, 0xf0, 0xad, 0xd4, 0xa2, 0xaf, 0x9c, 0xa4, 0x72, 0xc0, 0xb7, 0xfd, 0x93, 0x26, 0x36, 0x3f, 0xf7, 0xcc, 0x34, 0xa5, 0xe5, 0xf1, 0x71, 0xd8, 0x31, 0x15, 0x04, 0xc7, 0x23, 0xc3, 0x18, 0x96, 0x05, 0x9a, 0x07, 0x12, 0x80, 0xe2, 0xeb, 0x27, 0xb2, 0x75, 0x09, 0x83, 0x2c, 0x1a, 0x1b, 0x6e, 0x5a, 0xa0, 0x52, 0x3b, 0xd6, 0xb3, 0x29, 0xe3, 0x2f, 0x84, 0x53, 0xd1, 0x00, 0xed, 0x20, 0xfc, 0xb1, 0x5b, 0x6a, 0xcb, 0xbe, 0x39, 0x4a, 0x4c, 0x58, 0xcf, 0xd0, 0xef, 0xaa, 0xfb, 0x43, 0x4d, 0x33, 0x85, 0x45, 0xf9, 0x02, 0x7f, 0x50, 0x3c, 0x9f, 0xa8, 0x51, 0xa3, 0x40, 0x8f, 0x92, 0x9d, 0x38, 0xf5, 0xbc, 0xb6, 0xda, 0x21, 0x10, 0xff, 0xf3, 0xd2, 0xcd, 0x0c, 0x13, 0xec, 0x5f, 0x97, 0x44, 0x17, 0xc4, 0xa7, 0x7e, 0x3d, 0x64, 0x5d, 0x19, 0x73, 0x60, 0x81, 0x4f, 0xdc, 0x22, 0x2a, 0x90, 0x88, 0x46, 0xee, 0xb8, 0x14, 0xde, 0x5e, 0x0b, 0xdb, 0xe0, 0x32, 0x3a, 0x0a, 0x49, 0x06, 0x24, 0x5c, 0xc2, 0xd3, 0xac, 0x62, 0x91, 0x95, 0xe4, 0x79, 0xe7, 0xc8, 0x37, 0x6d, 0x8d, 0xd5, 0x4e, 0xa9, 0x6c, 0x56, 0xf4, 0xea, 0x65, 0x7a, 0xae, 0x08, 0xba, 0x78, 0x25, 0x2e, 0x1c, 0xa6, 0xb4, 0xc6, 0xe8, 0xdd, 0x74, 0x1f, 0x4b, 0xbd, 0x8b, 0x8a, 0x70, 0x3e, 0xb5, 0x66, 0x48, 0x03, 0xf6, 0x0e, 0x61, 0x35, 0x57, 0xb9, 0x86, 0xc1, 0x1d, 0x9e, 0xe1, 0xf8, 0x98, 0x11, 0x69, 0xd9, 0x8e, 0x94, 0x9b, 0x1e, 0x87, 0xe9, 0xce, 0x55, 0x28, 0xdf, 0x8c, 0xa1, 0x89, 0x0d, 0xbf, 0xe6, 0x42, 0x68, 0x41, 0x99, 0x2d, 0x0f, 0xb0, 0x54, 0xbb, 0x16 }; static const uint8_t rsbox[256] = { 0x52, 0x09, 0x6a, 0xd5, 0x30, 0x36, 0xa5, 0x38, 0xbf, 0x40, 0xa3, 0x9e, 0x81, 0xf3, 0xd7, 0xfb, 0x7c, 0xe3, 0x39, 0x82, 0x9b, 0x2f, 0xff, 0x87, 0x34, 0x8e, 0x43, 0x44, 0xc4, 0xde, 0xe9, 0xcb, 0x54, 0x7b, 0x94, 0x32, 0xa6, 0xc2, 0x23, 0x3d, 0xee, 0x4c, 0x95, 0x0b, 0x42, 0xfa, 0xc3, 0x4e, 0x08, 0x2e, 0xa1, 0x66, 0x28, 0xd9, 0x24, 0xb2, 0x76, 0x5b, 0xa2, 0x49, 0x6d, 0x8b, 0xd1, 0x25, 0x72, 0xf8, 0xf6, 0x64, 0x86, 0x68, 0x98, 0x16, 0xd4, 0xa4, 0x5c, 0xcc, 0x5d, 0x65, 0xb6, 0x92, 0x6c, 0x70, 0x48, 0x50, 0xfd, 0xed, 0xb9, 0xda, 0x5e, 0x15, 0x46, 0x57, 0xa7, 0x8d, 0x9d, 0x84, 0x90, 0xd8, 0xab, 0x00, 0x8c, 0xbc, 0xd3, 0x0a, 0xf7, 0xe4, 0x58, 0x05, 0xb8, 0xb3, 0x45, 0x06, 0xd0, 0x2c, 0x1e, 0x8f, 0xca, 0x3f, 0x0f, 0x02, 0xc1, 0xaf, 0xbd, 0x03, 0x01, 0x13, 0x8a, 0x6b, 0x3a, 0x91, 0x11, 0x41, 0x4f, 0x67, 0xdc, 0xea, 0x97, 0xf2, 0xcf, 0xce, 0xf0, 0xb4, 0xe6, 0x73, 0x96, 0xac, 0x74, 0x22, 0xe7, 0xad, 0x35, 0x85, 0xe2, 0xf9, 0x37, 0xe8, 0x1c, 0x75, 0xdf, 0x6e, 0x47, 0xf1, 0x1a, 0x71, 0x1d, 0x29, 0xc5, 0x89, 0x6f, 0xb7, 0x62, 0x0e, 0xaa, 0x18, 0xbe, 0x1b, 0xfc, 0x56, 0x3e, 0x4b, 0xc6, 0xd2, 0x79, 0x20, 0x9a, 0xdb, 0xc0, 0xfe, 0x78, 0xcd, 0x5a, 0xf4, 0x1f, 0xdd, 0xa8, 0x33, 0x88, 0x07, 0xc7, 0x31, 0xb1, 0x12, 0x10, 0x59, 0x27, 0x80, 0xec, 0x5f, 0x60, 0x51, 0x7f, 0xa9, 0x19, 0xb5, 0x4a, 0x0d, 0x2d, 0xe5, 0x7a, 0x9f, 0x93, 0xc9, 0x9c, 0xef, 0xa0, 0xe0, 0x3b, 0x4d, 0xae, 0x2a, 0xf5, 0xb0, 0xc8, 0xeb, 0xbb, 0x3c, 0x83, 0x53, 0x99, 0x61, 0x17, 0x2b, 0x04, 0x7e, 0xba, 0x77, 0xd6, 0x26, 0xe1, 0x69, 0x14, 0x63, 0x55, 0x21, 0x0c, 0x7d }; // The round constant word array, Rcon[i], contains the values given by // x to the power (i-1) being powers of x (x is denoted as {02}) in the field GF(2^8) static const uint8_t Rcon[11] = { 0x8d, 0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80, 0x1b, 0x36 }; /* * Jordan Goulder points out in PR #12 (https://github.com/kokke/tiny-AES-C/pull/12), * that you can remove most of the elements in the Rcon array, because they are unused. * * From Wikipedia's article on the Rijndael key schedule @ https://en.wikipedia.org/wiki/Rijndael_key_schedule#Rcon * * "Only the first some of these constants are actually used – up to rcon[10] for AES-128 (as 11 round keys are needed), * up to rcon[8] for AES-192, up to rcon[7] for AES-256. rcon[0] is not used in AES algorithm." */ /*****************************************************************************/ /* Private functions: */ /*****************************************************************************/ /* static uint8_t getSBoxValue(uint8_t num) { return sbox[num]; } */ #define getSBoxValue(num) (sbox[(num)]) /* static uint8_t getSBoxInvert(uint8_t num) { return rsbox[num]; } */ #define getSBoxInvert(num) (rsbox[(num)]) // This function produces Nb(Nr+1) round keys. The round keys are used in each round to decrypt the states. static void KeyExpansion(uint8_t* RoundKey, const uint8_t* Key) { unsigned i, j, k; uint8_t tempa[4]; // Used for the column/row operations // The first round key is the key itself. for (i = 0; i < Nk; ++i) { RoundKey[(i * 4) + 0] = Key[(i * 4) + 0]; RoundKey[(i * 4) + 1] = Key[(i * 4) + 1]; RoundKey[(i * 4) + 2] = Key[(i * 4) + 2]; RoundKey[(i * 4) + 3] = Key[(i * 4) + 3]; } // All other round keys are found from the previous round keys. for (i = Nk; i < Nb * (Nr + 1); ++i) { { k = (i - 1) * 4; tempa[0]=RoundKey[k + 0]; tempa[1]=RoundKey[k + 1]; tempa[2]=RoundKey[k + 2]; tempa[3]=RoundKey[k + 3]; } if (i % Nk == 0) { // This function shifts the 4 bytes in a word to the left once. // [a0,a1,a2,a3] becomes [a1,a2,a3,a0] // Function RotWord() { const uint8_t u8tmp = tempa[0]; tempa[0] = tempa[1]; tempa[1] = tempa[2]; tempa[2] = tempa[3]; tempa[3] = u8tmp; } // SubWord() is a function that takes a four-byte input word and // applies the S-box to each of the four bytes to produce an output word. // Function Subword() { tempa[0] = getSBoxValue(tempa[0]); tempa[1] = getSBoxValue(tempa[1]); tempa[2] = getSBoxValue(tempa[2]); tempa[3] = getSBoxValue(tempa[3]); } tempa[0] = tempa[0] ^ Rcon[i/Nk]; } #if defined(AES256) && (AES256 == 1) if (i % Nk == 4) { // Function Subword() { tempa[0] = getSBoxValue(tempa[0]); tempa[1] = getSBoxValue(tempa[1]); tempa[2] = getSBoxValue(tempa[2]); tempa[3] = getSBoxValue(tempa[3]); } } #endif j = i * 4; k=(i - Nk) * 4; RoundKey[j + 0] = RoundKey[k + 0] ^ tempa[0]; RoundKey[j + 1] = RoundKey[k + 1] ^ tempa[1]; RoundKey[j + 2] = RoundKey[k + 2] ^ tempa[2]; RoundKey[j + 3] = RoundKey[k + 3] ^ tempa[3]; } } void AES_init_ctx(struct AES_ctx* ctx, const uint8_t* key) { KeyExpansion(ctx->RoundKey, key); } #if (defined(CBC) && (CBC == 1)) || (defined(CTR) && (CTR == 1)) void AES_init_ctx_iv(struct AES_ctx* ctx, const uint8_t* key, const uint8_t* iv) { KeyExpansion(ctx->RoundKey, key); memcpy (ctx->Iv, iv, AES_BLOCKLEN); } void AES_ctx_set_iv(struct AES_ctx* ctx, const uint8_t* iv) { memcpy (ctx->Iv, iv, AES_BLOCKLEN); } #endif // This function adds the round key to state. // The round key is added to the state by an XOR function. static void AddRoundKey(uint8_t round, state_t* state, const uint8_t* RoundKey) { uint8_t i,j; for (i = 0; i < 4; ++i) { for (j = 0; j < 4; ++j) { (*state)[i][j] ^= RoundKey[(round * Nb * 4) + (i * Nb) + j]; } } } // The SubBytes Function Substitutes the values in the // state matrix with values in an S-box. static void SubBytes(state_t* state) { uint8_t i, j; for (i = 0; i < 4; ++i) { for (j = 0; j < 4; ++j) { (*state)[j][i] = getSBoxValue((*state)[j][i]); } } } // The ShiftRows() function shifts the rows in the state to the left. // Each row is shifted with different offset. // Offset = Row number. So the first row is not shifted. static void ShiftRows(state_t* state) { uint8_t temp; // Rotate first row 1 columns to left temp = (*state)[0][1]; (*state)[0][1] = (*state)[1][1]; (*state)[1][1] = (*state)[2][1]; (*state)[2][1] = (*state)[3][1]; (*state)[3][1] = temp; // Rotate second row 2 columns to left temp = (*state)[0][2]; (*state)[0][2] = (*state)[2][2]; (*state)[2][2] = temp; temp = (*state)[1][2]; (*state)[1][2] = (*state)[3][2]; (*state)[3][2] = temp; // Rotate third row 3 columns to left temp = (*state)[0][3]; (*state)[0][3] = (*state)[3][3]; (*state)[3][3] = (*state)[2][3]; (*state)[2][3] = (*state)[1][3]; (*state)[1][3] = temp; } static uint8_t xtime(uint8_t x) { return ((x<<1) ^ (((x>>7) & 1) * 0x1b)); } // MixColumns function mixes the columns of the state matrix static void MixColumns(state_t* state) { uint8_t i; uint8_t Tmp, Tm, t; for (i = 0; i < 4; ++i) { t = (*state)[i][0]; Tmp = (*state)[i][0] ^ (*state)[i][1] ^ (*state)[i][2] ^ (*state)[i][3] ; Tm = (*state)[i][0] ^ (*state)[i][1] ; Tm = xtime(Tm); (*state)[i][0] ^= Tm ^ Tmp ; Tm = (*state)[i][1] ^ (*state)[i][2] ; Tm = xtime(Tm); (*state)[i][1] ^= Tm ^ Tmp ; Tm = (*state)[i][2] ^ (*state)[i][3] ; Tm = xtime(Tm); (*state)[i][2] ^= Tm ^ Tmp ; Tm = (*state)[i][3] ^ t ; Tm = xtime(Tm); (*state)[i][3] ^= Tm ^ Tmp ; } } // Multiply is used to multiply numbers in the field GF(2^8) // Note: The last call to xtime() is unneeded, but often ends up generating a smaller binary // The compiler seems to be able to vectorize the operation better this way. // See https://github.com/kokke/tiny-AES-c/pull/34 #if MULTIPLY_AS_A_FUNCTION static uint8_t Multiply(uint8_t x, uint8_t y) { return (((y & 1) * x) ^ ((y>>1 & 1) * xtime(x)) ^ ((y>>2 & 1) * xtime(xtime(x))) ^ ((y>>3 & 1) * xtime(xtime(xtime(x)))) ^ ((y>>4 & 1) * xtime(xtime(xtime(xtime(x)))))); /* this last call to xtime() can be omitted */ } #else #define Multiply(x, y) \ ( ((y & 1) * x) ^ \ ((y>>1 & 1) * xtime(x)) ^ \ ((y>>2 & 1) * xtime(xtime(x))) ^ \ ((y>>3 & 1) * xtime(xtime(xtime(x)))) ^ \ ((y>>4 & 1) * xtime(xtime(xtime(xtime(x)))))) \ #endif #if (defined(CBC) && CBC == 1) || (defined(ECB) && ECB == 1) // MixColumns function mixes the columns of the state matrix. // The method used to multiply may be difficult to understand for the inexperienced. // Please use the references to gain more information. static void InvMixColumns(state_t* state) { int i; uint8_t a, b, c, d; for (i = 0; i < 4; ++i) { a = (*state)[i][0]; b = (*state)[i][1]; c = (*state)[i][2]; d = (*state)[i][3]; (*state)[i][0] = Multiply(a, 0x0e) ^ Multiply(b, 0x0b) ^ Multiply(c, 0x0d) ^ Multiply(d, 0x09); (*state)[i][1] = Multiply(a, 0x09) ^ Multiply(b, 0x0e) ^ Multiply(c, 0x0b) ^ Multiply(d, 0x0d); (*state)[i][2] = Multiply(a, 0x0d) ^ Multiply(b, 0x09) ^ Multiply(c, 0x0e) ^ Multiply(d, 0x0b); (*state)[i][3] = Multiply(a, 0x0b) ^ Multiply(b, 0x0d) ^ Multiply(c, 0x09) ^ Multiply(d, 0x0e); } } // The SubBytes Function Substitutes the values in the // state matrix with values in an S-box. static void InvSubBytes(state_t* state) { uint8_t i, j; for (i = 0; i < 4; ++i) { for (j = 0; j < 4; ++j) { (*state)[j][i] = getSBoxInvert((*state)[j][i]); } } } static void InvShiftRows(state_t* state) { uint8_t temp; // Rotate first row 1 columns to right temp = (*state)[3][1]; (*state)[3][1] = (*state)[2][1]; (*state)[2][1] = (*state)[1][1]; (*state)[1][1] = (*state)[0][1]; (*state)[0][1] = temp; // Rotate second row 2 columns to right temp = (*state)[0][2]; (*state)[0][2] = (*state)[2][2]; (*state)[2][2] = temp; temp = (*state)[1][2]; (*state)[1][2] = (*state)[3][2]; (*state)[3][2] = temp; // Rotate third row 3 columns to right temp = (*state)[0][3]; (*state)[0][3] = (*state)[1][3]; (*state)[1][3] = (*state)[2][3]; (*state)[2][3] = (*state)[3][3]; (*state)[3][3] = temp; } #endif // #if (defined(CBC) && CBC == 1) || (defined(ECB) && ECB == 1) // Cipher is the main function that encrypts the PlainText. static void Cipher(state_t* state, const uint8_t* RoundKey) { uint8_t round = 0; // Add the First round key to the state before starting the rounds. AddRoundKey(0, state, RoundKey); // There will be Nr rounds. // The first Nr-1 rounds are identical. // These Nr-1 rounds are executed in the loop below. for (round = 1; round < Nr; ++round) { SubBytes(state); ShiftRows(state); MixColumns(state); AddRoundKey(round, state, RoundKey); } // The last round is given below. // The MixColumns function is not here in the last round. SubBytes(state); ShiftRows(state); AddRoundKey(Nr, state, RoundKey); } #if (defined(CBC) && CBC == 1) || (defined(ECB) && ECB == 1) static void InvCipher(state_t* state, const uint8_t* RoundKey) { uint8_t round = 0; // Add the First round key to the state before starting the rounds. AddRoundKey(Nr, state, RoundKey); // There will be Nr rounds. // The first Nr-1 rounds are identical. // These Nr-1 rounds are executed in the loop below. for (round = (Nr - 1); round > 0; --round) { InvShiftRows(state); InvSubBytes(state); AddRoundKey(round, state, RoundKey); InvMixColumns(state); } // The last round is given below. // The MixColumns function is not here in the last round. InvShiftRows(state); InvSubBytes(state); AddRoundKey(0, state, RoundKey); } #endif // #if (defined(CBC) && CBC == 1) || (defined(ECB) && ECB == 1) /*****************************************************************************/ /* Public functions: */ /*****************************************************************************/ #if defined(ECB) && (ECB == 1) void AES_ECB_encrypt(const struct AES_ctx* ctx, uint8_t* buf) { // The next function call encrypts the PlainText with the Key using AES algorithm. Cipher((state_t*)buf, ctx->RoundKey); } void AES_ECB_decrypt(const struct AES_ctx* ctx, uint8_t* buf) { // The next function call decrypts the PlainText with the Key using AES algorithm. InvCipher((state_t*)buf, ctx->RoundKey); } #endif // #if defined(ECB) && (ECB == 1) #if defined(CBC) && (CBC == 1) static void XorWithIv(uint8_t* buf, const uint8_t* Iv) { uint8_t i; for (i = 0; i < AES_BLOCKLEN; ++i) // The block in AES is always 128bit no matter the key size { buf[i] ^= Iv[i]; } } void AES_CBC_encrypt_buffer(struct AES_ctx *ctx, uint8_t* buf, uint32_t length) { uintptr_t i; uint8_t *Iv = ctx->Iv; for (i = 0; i < length; i += AES_BLOCKLEN) { XorWithIv(buf, Iv); Cipher((state_t*)buf, ctx->RoundKey); Iv = buf; buf += AES_BLOCKLEN; //printf("Step %d - %d", i/16, i); } /* store Iv in ctx for next call */ memcpy(ctx->Iv, Iv, AES_BLOCKLEN); } void AES_CBC_decrypt_buffer(struct AES_ctx* ctx, uint8_t* buf, uint32_t length) { uintptr_t i; uint8_t storeNextIv[AES_BLOCKLEN]; for (i = 0; i < length; i += AES_BLOCKLEN) { memcpy(storeNextIv, buf, AES_BLOCKLEN); InvCipher((state_t*)buf, ctx->RoundKey); XorWithIv(buf, ctx->Iv); memcpy(ctx->Iv, storeNextIv, AES_BLOCKLEN); buf += AES_BLOCKLEN; } } #endif // #if defined(CBC) && (CBC == 1) #if defined(CTR) && (CTR == 1) /* Symmetrical operation: same function for encrypting as for decrypting. Note any IV/nonce should never be reused with the same key */ void AES_CTR_xcrypt_buffer(struct AES_ctx* ctx, uint8_t* buf, uint32_t length) { uint8_t buffer[AES_BLOCKLEN]; unsigned i; int bi; for (i = 0, bi = AES_BLOCKLEN; i < length; ++i, ++bi) { if (bi == AES_BLOCKLEN) /* we need to regen xor compliment in buffer */ { memcpy(buffer, ctx->Iv, AES_BLOCKLEN); Cipher((state_t*)buffer,ctx->RoundKey); /* Increment Iv and handle overflow */ for (bi = (AES_BLOCKLEN - 1); bi >= 0; --bi) { /* inc will overflow */ if (ctx->Iv[bi] == 255) { ctx->Iv[bi] = 0; continue; } ctx->Iv[bi] += 1; break; } bi = 0; } buf[i] = (buf[i] ^ buffer[bi]); } } #endif // #if defined(CTR) && (CTR == 1) dfx-mgr-xilinx_v2023.2/src/sys/linux/graph/aes128.h000066400000000000000000000052641446677152000217730ustar00rootroot00000000000000#ifndef _AES_H_ #define _AES_H_ #include // #define the macros below to 1/0 to enable/disable the mode of operation. // // CBC enables AES encryption in CBC-mode of operation. // CTR enables encryption in counter-mode. // ECB enables the basic ECB 16-byte block algorithm. All can be enabled simultaneously. // The #ifndef-guard allows it to be configured before #include'ing or at compile time. #ifndef CBC #define CBC 1 #endif #ifndef ECB #define ECB 1 #endif #ifndef CTR #define CTR 1 #endif #define AES128 1 //#define AES192 1 //#define AES256 1 #define AES_BLOCKLEN 16 //Block length in bytes AES is 128b block only #if defined(AES256) && (AES256 == 1) #define AES_KEYLEN 32 #define AES_keyExpSize 240 #elif defined(AES192) && (AES192 == 1) #define AES_KEYLEN 24 #define AES_keyExpSize 208 #else #define AES_KEYLEN 16 // Key length in bytes #define AES_keyExpSize 176 #endif struct AES_ctx { uint8_t RoundKey[AES_keyExpSize]; #if (defined(CBC) && (CBC == 1)) || (defined(CTR) && (CTR == 1)) uint8_t Iv[AES_BLOCKLEN]; #endif }; void AES_init_ctx(struct AES_ctx* ctx, const uint8_t* key); #if (defined(CBC) && (CBC == 1)) || (defined(CTR) && (CTR == 1)) void AES_init_ctx_iv(struct AES_ctx* ctx, const uint8_t* key, const uint8_t* iv); void AES_ctx_set_iv(struct AES_ctx* ctx, const uint8_t* iv); #endif #if defined(ECB) && (ECB == 1) // buffer size is exactly AES_BLOCKLEN bytes; // you need only AES_init_ctx as IV is not used in ECB // NB: ECB is considered insecure for most uses void AES_ECB_encrypt(const struct AES_ctx* ctx, uint8_t* buf); void AES_ECB_decrypt(const struct AES_ctx* ctx, uint8_t* buf); #endif // #if defined(ECB) && (ECB == !) #if defined(CBC) && (CBC == 1) // buffer size MUST be mutile of AES_BLOCKLEN; // Suggest https://en.wikipedia.org/wiki/Padding_(cryptography)#PKCS7 for padding scheme // NOTES: you need to set IV in ctx via AES_init_ctx_iv() or AES_ctx_set_iv() // no IV should ever be reused with the same key void AES_CBC_encrypt_buffer(struct AES_ctx* ctx, uint8_t* buf, uint32_t length); void AES_CBC_decrypt_buffer(struct AES_ctx* ctx, uint8_t* buf, uint32_t length); #endif // #if defined(CBC) && (CBC == 1) #if defined(CTR) && (CTR == 1) // Same function for encrypting as for decrypting. // IV is incremented for every block, and used after encryption as XOR-compliment for output // Suggesting https://en.wikipedia.org/wiki/Padding_(cryptography)#PKCS7 for padding scheme // NOTES: you need to set IV in ctx with AES_init_ctx_iv() or AES_ctx_set_iv() // no IV should ever be reused with the same key void AES_CTR_xcrypt_buffer(struct AES_ctx* ctx, uint8_t* buf, uint32_t length); #endif // #if defined(CTR) && (CTR == 1) #endif //_AES_H_ dfx-mgr-xilinx_v2023.2/src/sys/linux/graph/aes192.c000066400000000000000000000444371446677152000217740ustar00rootroot00000000000000/* This is an implementation of the AES algorithm, specifically ECB, CTR and CBC mode. Block size can be chosen in aes.h - available choices are AES128, AES192, AES256. The implementation is verified against the test vectors in: National Institute of Standards and Technology Special Publication 800-38A 2001 ED ECB-AES128 ---------- plain-text: 6bc1bee22e409f96e93d7e117393172a ae2d8a571e03ac9c9eb76fac45af8e51 30c81c46a35ce411e5fbc1191a0a52ef f69f2445df4f9b17ad2b417be66c3710 key: 2b7e151628aed2a6abf7158809cf4f3c resulting cipher 3ad77bb40d7a3660a89ecaf32466ef97 f5d3d58503b9699de785895a96fdbaaf 43b1cd7f598ece23881b00e3ed030688 7b0c785e27e8ad3f8223207104725dd4 NOTE: String length must be evenly divisible by 16byte (str_len % 16 == 0) You should pad the end of the string with zeros if this is not the case. For AES192/256 the key size is proportionally larger. */ /*****************************************************************************/ /* Includes: */ /*****************************************************************************/ #include #include // CBC mode, for memset #include "aes192.h" /*****************************************************************************/ /* Defines: */ /*****************************************************************************/ // The number of columns comprising a state in AES. This is a constant in AES. Value=4 #define Nb 4 #if defined(AES256) && (AES256 == 1) #define Nk 8 #define Nr 14 #elif defined(AES192) && (AES192 == 1) #define Nk 6 #define Nr 12 #else #define Nk 4 // The number of 32 bit words in a key. #define Nr 10 // The number of rounds in AES Cipher. #endif // jcallan@github points out that declaring Multiply as a function // reduces code size considerably with the Keil ARM compiler. // See this link for more information: https://github.com/kokke/tiny-AES-C/pull/3 #ifndef MULTIPLY_AS_A_FUNCTION #define MULTIPLY_AS_A_FUNCTION 0 #endif /*****************************************************************************/ /* Private variables: */ /*****************************************************************************/ // state - array holding the intermediate results during decryption. typedef uint8_t state_t[4][4]; // The lookup-tables are marked const so they can be placed in read-only storage instead of RAM // The numbers below can be computed dynamically trading ROM for RAM - // This can be useful in (embedded) bootloader applications, where ROM is often limited. static const uint8_t sbox[256] = { //0 1 2 3 4 5 6 7 8 9 A B C D E F 0x63, 0x7c, 0x77, 0x7b, 0xf2, 0x6b, 0x6f, 0xc5, 0x30, 0x01, 0x67, 0x2b, 0xfe, 0xd7, 0xab, 0x76, 0xca, 0x82, 0xc9, 0x7d, 0xfa, 0x59, 0x47, 0xf0, 0xad, 0xd4, 0xa2, 0xaf, 0x9c, 0xa4, 0x72, 0xc0, 0xb7, 0xfd, 0x93, 0x26, 0x36, 0x3f, 0xf7, 0xcc, 0x34, 0xa5, 0xe5, 0xf1, 0x71, 0xd8, 0x31, 0x15, 0x04, 0xc7, 0x23, 0xc3, 0x18, 0x96, 0x05, 0x9a, 0x07, 0x12, 0x80, 0xe2, 0xeb, 0x27, 0xb2, 0x75, 0x09, 0x83, 0x2c, 0x1a, 0x1b, 0x6e, 0x5a, 0xa0, 0x52, 0x3b, 0xd6, 0xb3, 0x29, 0xe3, 0x2f, 0x84, 0x53, 0xd1, 0x00, 0xed, 0x20, 0xfc, 0xb1, 0x5b, 0x6a, 0xcb, 0xbe, 0x39, 0x4a, 0x4c, 0x58, 0xcf, 0xd0, 0xef, 0xaa, 0xfb, 0x43, 0x4d, 0x33, 0x85, 0x45, 0xf9, 0x02, 0x7f, 0x50, 0x3c, 0x9f, 0xa8, 0x51, 0xa3, 0x40, 0x8f, 0x92, 0x9d, 0x38, 0xf5, 0xbc, 0xb6, 0xda, 0x21, 0x10, 0xff, 0xf3, 0xd2, 0xcd, 0x0c, 0x13, 0xec, 0x5f, 0x97, 0x44, 0x17, 0xc4, 0xa7, 0x7e, 0x3d, 0x64, 0x5d, 0x19, 0x73, 0x60, 0x81, 0x4f, 0xdc, 0x22, 0x2a, 0x90, 0x88, 0x46, 0xee, 0xb8, 0x14, 0xde, 0x5e, 0x0b, 0xdb, 0xe0, 0x32, 0x3a, 0x0a, 0x49, 0x06, 0x24, 0x5c, 0xc2, 0xd3, 0xac, 0x62, 0x91, 0x95, 0xe4, 0x79, 0xe7, 0xc8, 0x37, 0x6d, 0x8d, 0xd5, 0x4e, 0xa9, 0x6c, 0x56, 0xf4, 0xea, 0x65, 0x7a, 0xae, 0x08, 0xba, 0x78, 0x25, 0x2e, 0x1c, 0xa6, 0xb4, 0xc6, 0xe8, 0xdd, 0x74, 0x1f, 0x4b, 0xbd, 0x8b, 0x8a, 0x70, 0x3e, 0xb5, 0x66, 0x48, 0x03, 0xf6, 0x0e, 0x61, 0x35, 0x57, 0xb9, 0x86, 0xc1, 0x1d, 0x9e, 0xe1, 0xf8, 0x98, 0x11, 0x69, 0xd9, 0x8e, 0x94, 0x9b, 0x1e, 0x87, 0xe9, 0xce, 0x55, 0x28, 0xdf, 0x8c, 0xa1, 0x89, 0x0d, 0xbf, 0xe6, 0x42, 0x68, 0x41, 0x99, 0x2d, 0x0f, 0xb0, 0x54, 0xbb, 0x16 }; static const uint8_t rsbox[256] = { 0x52, 0x09, 0x6a, 0xd5, 0x30, 0x36, 0xa5, 0x38, 0xbf, 0x40, 0xa3, 0x9e, 0x81, 0xf3, 0xd7, 0xfb, 0x7c, 0xe3, 0x39, 0x82, 0x9b, 0x2f, 0xff, 0x87, 0x34, 0x8e, 0x43, 0x44, 0xc4, 0xde, 0xe9, 0xcb, 0x54, 0x7b, 0x94, 0x32, 0xa6, 0xc2, 0x23, 0x3d, 0xee, 0x4c, 0x95, 0x0b, 0x42, 0xfa, 0xc3, 0x4e, 0x08, 0x2e, 0xa1, 0x66, 0x28, 0xd9, 0x24, 0xb2, 0x76, 0x5b, 0xa2, 0x49, 0x6d, 0x8b, 0xd1, 0x25, 0x72, 0xf8, 0xf6, 0x64, 0x86, 0x68, 0x98, 0x16, 0xd4, 0xa4, 0x5c, 0xcc, 0x5d, 0x65, 0xb6, 0x92, 0x6c, 0x70, 0x48, 0x50, 0xfd, 0xed, 0xb9, 0xda, 0x5e, 0x15, 0x46, 0x57, 0xa7, 0x8d, 0x9d, 0x84, 0x90, 0xd8, 0xab, 0x00, 0x8c, 0xbc, 0xd3, 0x0a, 0xf7, 0xe4, 0x58, 0x05, 0xb8, 0xb3, 0x45, 0x06, 0xd0, 0x2c, 0x1e, 0x8f, 0xca, 0x3f, 0x0f, 0x02, 0xc1, 0xaf, 0xbd, 0x03, 0x01, 0x13, 0x8a, 0x6b, 0x3a, 0x91, 0x11, 0x41, 0x4f, 0x67, 0xdc, 0xea, 0x97, 0xf2, 0xcf, 0xce, 0xf0, 0xb4, 0xe6, 0x73, 0x96, 0xac, 0x74, 0x22, 0xe7, 0xad, 0x35, 0x85, 0xe2, 0xf9, 0x37, 0xe8, 0x1c, 0x75, 0xdf, 0x6e, 0x47, 0xf1, 0x1a, 0x71, 0x1d, 0x29, 0xc5, 0x89, 0x6f, 0xb7, 0x62, 0x0e, 0xaa, 0x18, 0xbe, 0x1b, 0xfc, 0x56, 0x3e, 0x4b, 0xc6, 0xd2, 0x79, 0x20, 0x9a, 0xdb, 0xc0, 0xfe, 0x78, 0xcd, 0x5a, 0xf4, 0x1f, 0xdd, 0xa8, 0x33, 0x88, 0x07, 0xc7, 0x31, 0xb1, 0x12, 0x10, 0x59, 0x27, 0x80, 0xec, 0x5f, 0x60, 0x51, 0x7f, 0xa9, 0x19, 0xb5, 0x4a, 0x0d, 0x2d, 0xe5, 0x7a, 0x9f, 0x93, 0xc9, 0x9c, 0xef, 0xa0, 0xe0, 0x3b, 0x4d, 0xae, 0x2a, 0xf5, 0xb0, 0xc8, 0xeb, 0xbb, 0x3c, 0x83, 0x53, 0x99, 0x61, 0x17, 0x2b, 0x04, 0x7e, 0xba, 0x77, 0xd6, 0x26, 0xe1, 0x69, 0x14, 0x63, 0x55, 0x21, 0x0c, 0x7d }; // The round constant word array, Rcon[i], contains the values given by // x to the power (i-1) being powers of x (x is denoted as {02}) in the field GF(2^8) static const uint8_t Rcon[11] = { 0x8d, 0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80, 0x1b, 0x36 }; /* * Jordan Goulder points out in PR #12 (https://github.com/kokke/tiny-AES-C/pull/12), * that you can remove most of the elements in the Rcon array, because they are unused. * * From Wikipedia's article on the Rijndael key schedule @ https://en.wikipedia.org/wiki/Rijndael_key_schedule#Rcon * * "Only the first some of these constants are actually used – up to rcon[10] for AES-128 (as 11 round keys are needed), * up to rcon[8] for AES-192, up to rcon[7] for AES-256. rcon[0] is not used in AES algorithm." */ /*****************************************************************************/ /* Private functions: */ /*****************************************************************************/ /* static uint8_t getSBoxValue(uint8_t num) { return sbox[num]; } */ #define getSBoxValue(num) (sbox[(num)]) /* static uint8_t getSBoxInvert(uint8_t num) { return rsbox[num]; } */ #define getSBoxInvert(num) (rsbox[(num)]) // This function produces Nb(Nr+1) round keys. The round keys are used in each round to decrypt the states. static void KeyExpansion(uint8_t* RoundKey, const uint8_t* Key) { unsigned i, j, k; uint8_t tempa[4]; // Used for the column/row operations // The first round key is the key itself. for (i = 0; i < Nk; ++i) { RoundKey[(i * 4) + 0] = Key[(i * 4) + 0]; RoundKey[(i * 4) + 1] = Key[(i * 4) + 1]; RoundKey[(i * 4) + 2] = Key[(i * 4) + 2]; RoundKey[(i * 4) + 3] = Key[(i * 4) + 3]; } // All other round keys are found from the previous round keys. for (i = Nk; i < Nb * (Nr + 1); ++i) { { k = (i - 1) * 4; tempa[0]=RoundKey[k + 0]; tempa[1]=RoundKey[k + 1]; tempa[2]=RoundKey[k + 2]; tempa[3]=RoundKey[k + 3]; } if (i % Nk == 0) { // This function shifts the 4 bytes in a word to the left once. // [a0,a1,a2,a3] becomes [a1,a2,a3,a0] // Function RotWord() { const uint8_t u8tmp = tempa[0]; tempa[0] = tempa[1]; tempa[1] = tempa[2]; tempa[2] = tempa[3]; tempa[3] = u8tmp; } // SubWord() is a function that takes a four-byte input word and // applies the S-box to each of the four bytes to produce an output word. // Function Subword() { tempa[0] = getSBoxValue(tempa[0]); tempa[1] = getSBoxValue(tempa[1]); tempa[2] = getSBoxValue(tempa[2]); tempa[3] = getSBoxValue(tempa[3]); } tempa[0] = tempa[0] ^ Rcon[i/Nk]; } #if defined(AES256) && (AES256 == 1) if (i % Nk == 4) { // Function Subword() { tempa[0] = getSBoxValue(tempa[0]); tempa[1] = getSBoxValue(tempa[1]); tempa[2] = getSBoxValue(tempa[2]); tempa[3] = getSBoxValue(tempa[3]); } } #endif j = i * 4; k=(i - Nk) * 4; RoundKey[j + 0] = RoundKey[k + 0] ^ tempa[0]; RoundKey[j + 1] = RoundKey[k + 1] ^ tempa[1]; RoundKey[j + 2] = RoundKey[k + 2] ^ tempa[2]; RoundKey[j + 3] = RoundKey[k + 3] ^ tempa[3]; } } void AES_192_init_ctx(struct AES_192_ctx* ctx, const uint8_t* key) { KeyExpansion(ctx->RoundKey, key); } #if (defined(CBC) && (CBC == 1)) || (defined(CTR) && (CTR == 1)) void AES_192_init_ctx_iv(struct AES_192_ctx* ctx, const uint8_t* key, const uint8_t* iv) { KeyExpansion(ctx->RoundKey, key); memcpy (ctx->Iv, iv, AES_BLOCKLEN); } void AES_192_ctx_set_iv(struct AES_192_ctx* ctx, const uint8_t* iv) { memcpy (ctx->Iv, iv, AES_BLOCKLEN); } #endif // This function adds the round key to state. // The round key is added to the state by an XOR function. static void AddRoundKey(uint8_t round, state_t* state, const uint8_t* RoundKey) { uint8_t i,j; for (i = 0; i < 4; ++i) { for (j = 0; j < 4; ++j) { (*state)[i][j] ^= RoundKey[(round * Nb * 4) + (i * Nb) + j]; } } } // The SubBytes Function Substitutes the values in the // state matrix with values in an S-box. static void SubBytes(state_t* state) { uint8_t i, j; for (i = 0; i < 4; ++i) { for (j = 0; j < 4; ++j) { (*state)[j][i] = getSBoxValue((*state)[j][i]); } } } // The ShiftRows() function shifts the rows in the state to the left. // Each row is shifted with different offset. // Offset = Row number. So the first row is not shifted. static void ShiftRows(state_t* state) { uint8_t temp; // Rotate first row 1 columns to left temp = (*state)[0][1]; (*state)[0][1] = (*state)[1][1]; (*state)[1][1] = (*state)[2][1]; (*state)[2][1] = (*state)[3][1]; (*state)[3][1] = temp; // Rotate second row 2 columns to left temp = (*state)[0][2]; (*state)[0][2] = (*state)[2][2]; (*state)[2][2] = temp; temp = (*state)[1][2]; (*state)[1][2] = (*state)[3][2]; (*state)[3][2] = temp; // Rotate third row 3 columns to left temp = (*state)[0][3]; (*state)[0][3] = (*state)[3][3]; (*state)[3][3] = (*state)[2][3]; (*state)[2][3] = (*state)[1][3]; (*state)[1][3] = temp; } static uint8_t xtime(uint8_t x) { return ((x<<1) ^ (((x>>7) & 1) * 0x1b)); } // MixColumns function mixes the columns of the state matrix static void MixColumns(state_t* state) { uint8_t i; uint8_t Tmp, Tm, t; for (i = 0; i < 4; ++i) { t = (*state)[i][0]; Tmp = (*state)[i][0] ^ (*state)[i][1] ^ (*state)[i][2] ^ (*state)[i][3] ; Tm = (*state)[i][0] ^ (*state)[i][1] ; Tm = xtime(Tm); (*state)[i][0] ^= Tm ^ Tmp ; Tm = (*state)[i][1] ^ (*state)[i][2] ; Tm = xtime(Tm); (*state)[i][1] ^= Tm ^ Tmp ; Tm = (*state)[i][2] ^ (*state)[i][3] ; Tm = xtime(Tm); (*state)[i][2] ^= Tm ^ Tmp ; Tm = (*state)[i][3] ^ t ; Tm = xtime(Tm); (*state)[i][3] ^= Tm ^ Tmp ; } } // Multiply is used to multiply numbers in the field GF(2^8) // Note: The last call to xtime() is unneeded, but often ends up generating a smaller binary // The compiler seems to be able to vectorize the operation better this way. // See https://github.com/kokke/tiny-AES-c/pull/34 #if MULTIPLY_AS_A_FUNCTION static uint8_t Multiply(uint8_t x, uint8_t y) { return (((y & 1) * x) ^ ((y>>1 & 1) * xtime(x)) ^ ((y>>2 & 1) * xtime(xtime(x))) ^ ((y>>3 & 1) * xtime(xtime(xtime(x)))) ^ ((y>>4 & 1) * xtime(xtime(xtime(xtime(x)))))); /* this last call to xtime() can be omitted */ } #else #define Multiply(x, y) \ ( ((y & 1) * x) ^ \ ((y>>1 & 1) * xtime(x)) ^ \ ((y>>2 & 1) * xtime(xtime(x))) ^ \ ((y>>3 & 1) * xtime(xtime(xtime(x)))) ^ \ ((y>>4 & 1) * xtime(xtime(xtime(xtime(x)))))) \ #endif #if (defined(CBC) && CBC == 1) || (defined(ECB) && ECB == 1) // MixColumns function mixes the columns of the state matrix. // The method used to multiply may be difficult to understand for the inexperienced. // Please use the references to gain more information. static void InvMixColumns(state_t* state) { int i; uint8_t a, b, c, d; for (i = 0; i < 4; ++i) { a = (*state)[i][0]; b = (*state)[i][1]; c = (*state)[i][2]; d = (*state)[i][3]; (*state)[i][0] = Multiply(a, 0x0e) ^ Multiply(b, 0x0b) ^ Multiply(c, 0x0d) ^ Multiply(d, 0x09); (*state)[i][1] = Multiply(a, 0x09) ^ Multiply(b, 0x0e) ^ Multiply(c, 0x0b) ^ Multiply(d, 0x0d); (*state)[i][2] = Multiply(a, 0x0d) ^ Multiply(b, 0x09) ^ Multiply(c, 0x0e) ^ Multiply(d, 0x0b); (*state)[i][3] = Multiply(a, 0x0b) ^ Multiply(b, 0x0d) ^ Multiply(c, 0x09) ^ Multiply(d, 0x0e); } } // The SubBytes Function Substitutes the values in the // state matrix with values in an S-box. static void InvSubBytes(state_t* state) { uint8_t i, j; for (i = 0; i < 4; ++i) { for (j = 0; j < 4; ++j) { (*state)[j][i] = getSBoxInvert((*state)[j][i]); } } } static void InvShiftRows(state_t* state) { uint8_t temp; // Rotate first row 1 columns to right temp = (*state)[3][1]; (*state)[3][1] = (*state)[2][1]; (*state)[2][1] = (*state)[1][1]; (*state)[1][1] = (*state)[0][1]; (*state)[0][1] = temp; // Rotate second row 2 columns to right temp = (*state)[0][2]; (*state)[0][2] = (*state)[2][2]; (*state)[2][2] = temp; temp = (*state)[1][2]; (*state)[1][2] = (*state)[3][2]; (*state)[3][2] = temp; // Rotate third row 3 columns to right temp = (*state)[0][3]; (*state)[0][3] = (*state)[1][3]; (*state)[1][3] = (*state)[2][3]; (*state)[2][3] = (*state)[3][3]; (*state)[3][3] = temp; } #endif // #if (defined(CBC) && CBC == 1) || (defined(ECB) && ECB == 1) // Cipher is the main function that encrypts the PlainText. static void Cipher(state_t* state, const uint8_t* RoundKey) { uint8_t round = 0; // Add the First round key to the state before starting the rounds. AddRoundKey(0, state, RoundKey); // There will be Nr rounds. // The first Nr-1 rounds are identical. // These Nr-1 rounds are executed in the loop below. for (round = 1; round < Nr; ++round) { SubBytes(state); ShiftRows(state); MixColumns(state); AddRoundKey(round, state, RoundKey); } // The last round is given below. // The MixColumns function is not here in the last round. SubBytes(state); ShiftRows(state); AddRoundKey(Nr, state, RoundKey); } #if (defined(CBC) && CBC == 1) || (defined(ECB) && ECB == 1) static void InvCipher(state_t* state, const uint8_t* RoundKey) { uint8_t round = 0; // Add the First round key to the state before starting the rounds. AddRoundKey(Nr, state, RoundKey); // There will be Nr rounds. // The first Nr-1 rounds are identical. // These Nr-1 rounds are executed in the loop below. for (round = (Nr - 1); round > 0; --round) { InvShiftRows(state); InvSubBytes(state); AddRoundKey(round, state, RoundKey); InvMixColumns(state); } // The last round is given below. // The MixColumns function is not here in the last round. InvShiftRows(state); InvSubBytes(state); AddRoundKey(0, state, RoundKey); } #endif // #if (defined(CBC) && CBC == 1) || (defined(ECB) && ECB == 1) /*****************************************************************************/ /* Public functions: */ /*****************************************************************************/ #if defined(ECB) && (ECB == 1) void AES_192_ECB_encrypt(const struct AES_192_ctx* ctx, uint8_t* buf) { // The next function call encrypts the PlainText with the Key using AES algorithm. Cipher((state_t*)buf, ctx->RoundKey); } void AES_192_ECB_decrypt(const struct AES_192_ctx* ctx, uint8_t* buf) { // The next function call decrypts the PlainText with the Key using AES algorithm. InvCipher((state_t*)buf, ctx->RoundKey); } #endif // #if defined(ECB) && (ECB == 1) #if defined(CBC) && (CBC == 1) static void XorWithIv(uint8_t* buf, const uint8_t* Iv) { uint8_t i; for (i = 0; i < AES_BLOCKLEN; ++i) // The block in AES is always 128bit no matter the key size { buf[i] ^= Iv[i]; } } void AES_192_CBC_encrypt_buffer(struct AES_192_ctx *ctx, uint8_t* buf, uint32_t length) { uintptr_t i; uint8_t *Iv = ctx->Iv; for (i = 0; i < length; i += AES_BLOCKLEN) { XorWithIv(buf, Iv); Cipher((state_t*)buf, ctx->RoundKey); Iv = buf; buf += AES_BLOCKLEN; //printf("Step %d - %d", i/16, i); } /* store Iv in ctx for next call */ memcpy(ctx->Iv, Iv, AES_BLOCKLEN); } void AES_192_CBC_decrypt_buffer(struct AES_192_ctx* ctx, uint8_t* buf, uint32_t length) { uintptr_t i; uint8_t storeNextIv[AES_BLOCKLEN]; for (i = 0; i < length; i += AES_BLOCKLEN) { memcpy(storeNextIv, buf, AES_BLOCKLEN); InvCipher((state_t*)buf, ctx->RoundKey); XorWithIv(buf, ctx->Iv); memcpy(ctx->Iv, storeNextIv, AES_BLOCKLEN); buf += AES_BLOCKLEN; } } #endif // #if defined(CBC) && (CBC == 1) #if defined(CTR) && (CTR == 1) /* Symmetrical operation: same function for encrypting as for decrypting. Note any IV/nonce should never be reused with the same key */ void AES_192_CTR_xcrypt_buffer(struct AES_192_ctx* ctx, uint8_t* buf, uint32_t length) { uint8_t buffer[AES_BLOCKLEN]; unsigned i; int bi; for (i = 0, bi = AES_BLOCKLEN; i < length; ++i, ++bi) { if (bi == AES_BLOCKLEN) /* we need to regen xor compliment in buffer */ { memcpy(buffer, ctx->Iv, AES_BLOCKLEN); Cipher((state_t*)buffer,ctx->RoundKey); /* Increment Iv and handle overflow */ for (bi = (AES_BLOCKLEN - 1); bi >= 0; --bi) { /* inc will overflow */ if (ctx->Iv[bi] == 255) { ctx->Iv[bi] = 0; continue; } ctx->Iv[bi] += 1; break; } bi = 0; } buf[i] = (buf[i] ^ buffer[bi]); } } #endif // #if defined(CTR) && (CTR == 1) dfx-mgr-xilinx_v2023.2/src/sys/linux/graph/aes192.h000066400000000000000000000053701446677152000217720ustar00rootroot00000000000000#ifndef _AES_H_ #define _AES_H_ #include // #define the macros below to 1/0 to enable/disable the mode of operation. // // CBC enables AES encryption in CBC-mode of operation. // CTR enables encryption in counter-mode. // ECB enables the basic ECB 16-byte block algorithm. All can be enabled simultaneously. // The #ifndef-guard allows it to be configured before #include'ing or at compile time. #ifndef CBC #define CBC 1 #endif #ifndef ECB #define ECB 1 #endif #ifndef CTR #define CTR 1 #endif //#define AES128 1 #define AES192 1 //#define AES256 1 #define AES_BLOCKLEN 16 //Block length in bytes AES is 128b block only #if defined(AES256) && (AES256 == 1) #define AES_KEYLEN 32 #define AES_keyExpSize 240 #elif defined(AES192) && (AES192 == 1) #define AES_KEYLEN 24 #define AES_keyExpSize 208 #else #define AES_KEYLEN 16 // Key length in bytes #define AES_keyExpSize 176 #endif struct AES_192_ctx { uint8_t RoundKey[AES_keyExpSize]; #if (defined(CBC) && (CBC == 1)) || (defined(CTR) && (CTR == 1)) uint8_t Iv[AES_BLOCKLEN]; #endif }; void AES_192_init_ctx(struct AES_192_ctx* ctx, const uint8_t* key); #if (defined(CBC) && (CBC == 1)) || (defined(CTR) && (CTR == 1)) void AES_192_init_ctx_iv(struct AES_192_ctx* ctx, const uint8_t* key, const uint8_t* iv); void AES_192_ctx_set_iv(struct AES_192_ctx* ctx, const uint8_t* iv); #endif #if defined(ECB) && (ECB == 1) // buffer size is exactly AES_BLOCKLEN bytes; // you need only AES_init_ctx as IV is not used in ECB // NB: ECB is considered insecure for most uses void AES_192_ECB_encrypt(const struct AES_192_ctx* ctx, uint8_t* buf); void AES_192_ECB_decrypt(const struct AES_192_ctx* ctx, uint8_t* buf); #endif // #if defined(ECB) && (ECB == !) #if defined(CBC) && (CBC == 1) // buffer size MUST be mutile of AES_BLOCKLEN; // Suggest https://en.wikipedia.org/wiki/Padding_(cryptography)#PKCS7 for padding scheme // NOTES: you need to set IV in ctx via AES_init_ctx_iv() or AES_ctx_set_iv() // no IV should ever be reused with the same key void AES_192_CBC_encrypt_buffer(struct AES_192_ctx* ctx, uint8_t* buf, uint32_t length); void AES_192_CBC_decrypt_buffer(struct AES_192_ctx* ctx, uint8_t* buf, uint32_t length); #endif // #if defined(CBC) && (CBC == 1) #if defined(CTR) && (CTR == 1) // Same function for encrypting as for decrypting. // IV is incremented for every block, and used after encryption as XOR-compliment for output // Suggesting https://en.wikipedia.org/wiki/Padding_(cryptography)#PKCS7 for padding scheme // NOTES: you need to set IV in ctx with AES_init_ctx_iv() or AES_ctx_set_iv() // no IV should ever be reused with the same key void AES_192_CTR_xcrypt_buffer(struct AES_192_ctx* ctx, uint8_t* buf, uint32_t length); #endif // #if defined(CTR) && (CTR == 1) #endif //_AES_H_ dfx-mgr-xilinx_v2023.2/src/sys/linux/graph/aes192Fallback.c000066400000000000000000000024301446677152000233770ustar00rootroot00000000000000/* * Copyright (c) 2021, Xilinx Inc. and Contributors. All rights reserved. * * SPDX-License-Identifier: MIT */ #include #include #include #include #include "layer0/utils.h" #include "aes192.h" #include #include #define BLOCKSIZE 16 int encrypt192Buffer(unsigned char* key, unsigned char* buffer, int bytes){ struct AES_192_ctx ctx; int i; AES_192_init_ctx(&ctx, key); for (i = 0; i < bytes/BLOCKSIZE; i++){ AES_192_ECB_encrypt(&ctx, &buffer[BLOCKSIZE * i]); } return 0; } int decrypt192Buffer(unsigned char* key, unsigned char* buffer, int bytes){ struct AES_192_ctx ctx; int i; AES_192_init_ctx(&ctx, key); for (i = 0; i < bytes/BLOCKSIZE; i++){ AES_192_ECB_decrypt(&ctx, &buffer[BLOCKSIZE * i]); } return 0; } int softgAES192(void** inData, int* inDataSize, void** outData, int* outDataSize){ INFO("soft AES192 FALLBACK CALLED !!\n"); _unused(outDataSize); int DOENC = 0; uint8_t key[32]; if(inData[1] != NULL){ memcpy(key, inData[1], 16); DOENC = *((uint8_t*)inData[1] + 16); } if (DOENC){ encrypt192Buffer(key, inData[0], inDataSize[0]); } else{ decrypt192Buffer(key, inData[0], inDataSize[0]); } memcpy((void*)outData[0], (void*)inData[0], inDataSize[0]); return 0; } dfx-mgr-xilinx_v2023.2/src/sys/linux/graph/aes192Fallback.h000066400000000000000000000001341446677152000234030ustar00rootroot00000000000000 extern int softgAES192(void** inData, int* inDataSize, void** outData, int* outDataSize); dfx-mgr-xilinx_v2023.2/src/sys/linux/graph/aesFallback.c000066400000000000000000000044611446677152000231510ustar00rootroot00000000000000/* * Copyright (c) 2021, Xilinx Inc. and Contributors. All rights reserved. * * SPDX-License-Identifier: MIT */ #include #include #include #include #include "layer0/utils.h" #include "aes128.h" #include #include #define BLOCKSIZE 16 int encrypt128Buffer(unsigned char* key, unsigned char* buffer, int bytes){ struct AES_ctx ctx; int i; AES_init_ctx(&ctx, key); for (i = 0; i < bytes/BLOCKSIZE; i++){ AES_ECB_encrypt(&ctx, &buffer[BLOCKSIZE * i]); } return 0; } int decrypt128Buffer(unsigned char* key, unsigned char* buffer, int bytes){ struct AES_ctx ctx; int i; AES_init_ctx(&ctx, key); for (i = 0; i < bytes/BLOCKSIZE; i++){ AES_ECB_decrypt(&ctx, &buffer[BLOCKSIZE * i]); } return 0; } /* int encrypt192Buffer(unsigned char* key, unsigned char* buffer, int bytes){ struct AES_192_ctx ctx; int i; AES_192_init_ctx(&ctx, key); for (i = 0; i < bytes/BLOCKSIZE; i++){ AES_192_ECB_encrypt(&ctx, &buffer[BLOCKSIZE * i]); } return 0; } int decrypt192Buffer(unsigned char* key, unsigned char* buffer, int bytes){ struct AES_192_ctx ctx; int i; AES_192_init_ctx(&ctx, key); for (i = 0; i < bytes/BLOCKSIZE; i++){ AES_192_ECB_decrypt(&ctx, &buffer[BLOCKSIZE * i]); } return 0; } */ int softgAES128(void** inData, int* inDataSize, void** outData, int* outDataSize){ INFO("soft AES128 FALLBACK CALLED !!\n"); _unused(outDataSize); int DOENC = 0; uint8_t key[32]; if(inData[1] != NULL){ memcpy(key, inData[1], 16); DOENC = *((uint8_t*)inData[1] + 16); } if (DOENC){ encrypt128Buffer(key, inData[0], inDataSize[0]); } else{ decrypt128Buffer(key, inData[0], inDataSize[0]); } memcpy((void*)outData[0], (void*)inData[0], inDataSize[0]); return 0; } /* int softgAES192(void** inData, int* inDataSize, void** outData, int* outDataSize){ INFO("soft AES128 FALLBACK CALLED !!\n"); _unused(outDataSize); int DOENC = 0; uint8_t key[32]; if(inData[1] != NULL){ memcpy(key, inData[1], 16); DOENC = *((uint8_t*)inData[1] + 16); } if (DOENC){ encrypt192Buffer(key, inData[0], inDataSize[0]); } else{ decrypt192Buffer(key, inData[0], inDataSize[0]); } memcpy((void*)outData[0], (void*)inData[0], inDataSize[0]); return 0; } */ dfx-mgr-xilinx_v2023.2/src/sys/linux/graph/aesFallback.h000066400000000000000000000001341446677152000231470ustar00rootroot00000000000000 extern int softgAES128(void** inData, int* inDataSize, void** outData, int* outDataSize); dfx-mgr-xilinx_v2023.2/src/sys/linux/graph/graph.c000066400000000000000000000756751446677152000221010ustar00rootroot00000000000000/* * Copyright (c) 2021, Xilinx Inc. and Contributors. All rights reserved. * * SPDX-License-Identifier: MIT */ #include #include #include #include #include #include #include #include "layer0/sihaHLS/sihaHLSdm.h" #include "layer0/softIO/softdm.h" #include "layer0/fallback/fallback.h" #include "graph.h" #include "layer0/utils.h" #include "layer0/siha.h" #include "scheduler.h" #include #include AccelNode_t* createAccelNode(char *name, int inDmaType, int outDmaType, FALLBACKFUNCTION fallbackfunction, int InterRMCompatible, int SchedulerBypassFlag){ //INFO("\n"); AccelNode_t *nextAccel = (AccelNode_t *) malloc(sizeof(AccelNode_t)); strcpy(nextAccel->accel.name, name); nextAccel->accel.inDmaType = inDmaType; nextAccel->accel.outDmaType = outDmaType; nextAccel->accel.fallbackfunction = fallbackfunction; nextAccel->accel.InterRMCompatible = InterRMCompatible; nextAccel->accel.SchedulerBypassFlag = SchedulerBypassFlag; nextAccel->S2MMStatus = 0; nextAccel->MM2SStatus = 0; nextAccel->currentTransactionIndex = 0; nextAccel->head = NULL; nextAccel->tail = NULL; //INFO("\n"); return nextAccel; } AccelNode_t* addAccelNode(AccelNode_t **accelNode, AccelNode_t *nextAccel){ //INFO("\n"); int index = -1; AccelNode_t *accel = *accelNode; if(accel != NULL){ if(index < accel->accel.index){ index = accel->accel.index; } while((accel)->tail != NULL){ accel = accel->tail; if(index < accel->accel.index){ index = accel->accel.index; } } accel->tail = nextAccel; nextAccel->head = accel; nextAccel->accel.index = index; } else{ *accelNode = nextAccel; } nextAccel->accel.index = index + 1; if(nextAccel->accel.type == IO_NODE || nextAccel->accel.type == IN_NODE || nextAccel->accel.type == OUT_NODE){ nextAccel->accel.inHardware = 0; nextAccel->accel.datamover = malloc(sizeof(dm_t)); nextAccel->accel.status = 0; soft_register(nextAccel->accel.datamover); //INFO("%p\n", nextAccel->accel.semptr); nextAccel->accel.datamover->config(nextAccel->accel.datamover->dmstruct, &(nextAccel->accel)); ///TaskInit(nextAccel->accel.datamover); } else if(nextAccel->accel.type == SW_NODE){ //INFO("SW NODE SELECTED\n"); nextAccel->accel.inHardware = 0; nextAccel->accel.datamover = malloc(sizeof(dm_t)); nextAccel->accel.status = 0; fallback_register(nextAccel->accel.datamover, 1, 1, nextAccel->accel.fallbackfunction); //nextAccel->accel.datamover->config(nextAccel->accel.datamover->dmstruct, nextAccel->accel.dma_hls); nextAccel->accel.datamover->config(nextAccel->accel.datamover->dmstruct, &(nextAccel->accel)); //.dma_hls); //TaskInit(nextAccel->accel.datamover); } else if(nextAccel->accel.type == HW_NODE){ //INFO("%d, %s\n", nextAccel->accel.index, nextAccel->accel.name); int status = SIHAInitAccel(nextAccel->accel.index, nextAccel->accel.name); if(status < 0){ nextAccel->accel.inHardware = 0; nextAccel->accel.datamover = malloc(sizeof(dm_t)); nextAccel->accel.status = 0; fallback_register(nextAccel->accel.datamover, 1, 1, nextAccel->accel.fallbackfunction); //nextAccel->accel.datamover->config(nextAccel->accel.datamover->dmstruct, nextAccel->accel.dma_hls); nextAccel->accel.datamover->config(nextAccel->accel.datamover->dmstruct, &(nextAccel->accel)); //.dma_hls); //TaskInit(nextAccel->accel.datamover); } else{ nextAccel->accel.inHardware = 1; //INFO("$$$\n"); plDevices_t* pldevices = SIHAGetPLDevices(); nextAccel->accel.AccelConfig_fd = pldevices->AccelConfig_fd[nextAccel->accel.index]; nextAccel->accel.dma_hls_fd = pldevices->dma_hls_fd[nextAccel->accel.index]; nextAccel->accel.AccelConfig = pldevices->AccelConfig[nextAccel->accel.index]; nextAccel->accel.dma_hls = pldevices->dma_hls[nextAccel->accel.index]; nextAccel->accel.slot = pldevices->slot[nextAccel->accel.index]; nextAccel->accel.datamover = malloc(sizeof(dm_t)); nextAccel->accel.status = 0; sihahls_register(nextAccel->accel.datamover); sihahls_DMConfig_t* dmconfig = (sihahls_DMConfig_t*)nextAccel->accel.datamover->dmstruct; _unused(dmconfig); nextAccel->accel.datamover->config(nextAccel->accel.datamover->dmstruct, &(nextAccel->accel)); //TaskInit(nextAccel->accel.datamover); } } return nextAccel; } int delAccelNode(AccelNode_t** accelNode){ //INFO("\n"); AccelNode_t *tAccelNode = *accelNode; AccelNode_t *headAccel = tAccelNode->head; AccelNode_t *tailAccel = tAccelNode->tail; if(headAccel != NULL){ headAccel->tail = tailAccel; } else{ *accelNode = tailAccel; } if(tailAccel != NULL){ tailAccel->head = headAccel; } if(tAccelNode->accel.type == IO_NODE || tAccelNode->accel.type == IN_NODE || tAccelNode->accel.type == OUT_NODE){ //TaskFinalise(tAccelNode->accel.datamover); soft_unregister(tAccelNode->accel.datamover); free(tAccelNode->accel.datamover); } else if(tAccelNode->accel.type == SW_NODE){ //TaskFinalise(tAccelNode->accel.datamover); fallback_unregister(tAccelNode->accel.datamover); free(tAccelNode->accel.datamover); } else if(tAccelNode->accel.type == HW_NODE){ INFO("%d\n", tAccelNode->accel.inHardware); if(tAccelNode->accel.inHardware){ //TaskFinalise(tAccelNode->accel.datamover); sihahls_unregister(tAccelNode->accel.datamover); free(tAccelNode->accel.datamover); SIHAFinaliseAccel(tAccelNode->accel.index); //INFO("############\n"); } else { //TaskFinalise(tAccelNode->accel.datamover); fallback_unregister(tAccelNode->accel.datamover); free(tAccelNode->accel.datamover); } } free(tAccelNode); return 0; } int printAccelInfo(Accel_t accel, char* json){ //INFO("\n"); int len = sprintf(json, "{\"node\": \"%s_%x\", \"type\": %d, \"inDmaType\": %d, \"outDmaType\": %d, \"size\": %ld", accel.name, accel.index, accel.type, accel.inDmaType, accel.outDmaType, accel.softBufferSize); if(accel.AccelConfig){ len += sprintf(json + len, ", \"AccelConfig_fd\": %d, \"dma_hls_fd\": %d, \"AccelConfig\": \"%p\", \"dma_hls\": \"%p\", \"slot\": %d, \"InterRMCompatible\": %d}", accel.AccelConfig_fd, accel.dma_hls_fd, accel.AccelConfig, accel.dma_hls, accel.slot, accel.InterRMCompatible); } else{ len += sprintf(json + len, "}"); } return len; } int printAccelNodes(AccelNode_t *accelNode, char* json){ //INFO("\n"); int len = 0; if(accelNode != NULL){ len += printAccelInfo(accelNode->accel, json); if(accelNode->tail != NULL){ len += sprintf(json + len, ",\n"); } len += printAccelNodes(accelNode->tail, json + len); } return len; } int printAccelNodesInfo(AccelNode_t *accelNode, char* json){ //INFO("\n"); int len = 0; len += sprintf(json, "{\"nodes\": ["); len += printAccelNodes(accelNode, json + len); len += sprintf(json + len, "],\n"); return len; } BuffNode_t* createBuffNode(int size, char *name, int type){ //INFO("\n"); BuffNode_t *nextBuff = (BuffNode_t *) malloc(sizeof(BuffNode_t)); nextBuff->head = NULL; nextBuff->tail = NULL; nextBuff->buffer.size = size; nextBuff->buffer.type = type; nextBuff->buffer.fd = 0; nextBuff->buffer.handle = 0; nextBuff->buffer.ptr = NULL; nextBuff->buffer.phyAddr = 0; nextBuff->buffer.srcSlot = 0; nextBuff->buffer.sincSlot = 0; nextBuff->readStatus = 0; nextBuff->buffer.index = 0; nextBuff->status = 0; nextBuff->buffer.otherAccel_phyAddr[0] = 0x200000000; nextBuff->buffer.otherAccel_phyAddr[1] = 0x280000000; nextBuff->buffer.otherAccel_phyAddr[2] = 0x300000000; nextBuff->buffer.readerCount = 0; nextBuff->buffer.readStatus = 0; nextBuff->buffer.writeStatus = 0; nextBuff->buffer.InterRMCompatible = 0; strcpy(nextBuff->buffer.name, name); return nextBuff; } BuffNode_t* addBuffNode(BuffNode_t** buffNode, BuffNode_t* nextBuff){ //INFO("\n"); int index = -1; BuffNode_t *buff = *buffNode; if(buff != NULL){ if(index < buff->buffer.index){ index = buff->buffer.index; } while(buff->tail != NULL){ buff = buff->tail; if(index < buff->buffer.index){ index = buff->buffer.index; } } buff->tail = nextBuff; nextBuff->head = buff; } else{ *buffNode = nextBuff; } nextBuff->buffer.index = index + 1; //printf("%d\n", nextBuff->buffer.index); return nextBuff; } int delBuffNode(BuffNode_t** buffNode, int drm_fd){ //INFO("\n"); BuffNode_t *tBuffNode = *buffNode; BuffNode_t *headBuff = tBuffNode->head; BuffNode_t *tailBuff = tBuffNode->tail; if(headBuff != NULL){ headBuff->tail = tailBuff; }else{ *buffNode = tailBuff; } if(tailBuff != NULL){ tailBuff->head = headBuff; } if(tBuffNode->buffer.handle){ //INFO("deallocate Buffer handle: %d\n", tBuffNode->buffer.handle); close(tBuffNode->buffer.fd); xrt_deallocateBuffer(drm_fd, tBuffNode->buffer.size, &tBuffNode->buffer.handle, &tBuffNode->buffer.ptr, &tBuffNode->buffer.phyAddr); tBuffNode->buffer.ptr = NULL; tBuffNode->buffer.phyAddr = 0; tBuffNode->buffer.size = 0; } free(tBuffNode); return 0; } int printBuffInfo(DFXBuffer_t buffer, char* json){ //INFO("\n"); int len = sprintf(json, "{\"node\": \"%s_%x\", \"type\": %d, ", buffer.name, buffer.index, buffer.type); len += sprintf(json + len, "\"fd\": %d, \"size\": %d, \"handle\": %d, ", buffer.fd, buffer.size, buffer.handle); len += sprintf(json + len, "\"ptr\": \"%p\", \"phyAddr\": \"%lx\", \"InterRMCompatible\": %d}", buffer.ptr, buffer.phyAddr, buffer.InterRMCompatible); return len; } int printBuffNodes(BuffNode_t *buffNode, char* json){ //INFO("\n"); int len = 0; if(buffNode != NULL){ len += printBuffInfo(buffNode->buffer, json); if(buffNode->tail != NULL){ len += sprintf(json + len, ",\n"); } len += printBuffNodes(buffNode->tail, json + len); } return len; } int printBuffNodesInfo(BuffNode_t *buffNode, char* json){ //INFO("\n"); int len = 0; len += sprintf(json, "\"buffnodes\": ["); len += printBuffNodes(buffNode, json + len); len += sprintf(json + len, "],\n"); return len; } Link_t* addLink(Link_t** link, Link_t* nextLink){ //INFO("\n"); Link_t *tlink = *link; if(tlink != NULL){ while(tlink->tail != NULL){ tlink = tlink->tail; } tlink->tail = nextLink; nextLink->head = tlink; } else{ *link = nextLink; } return nextLink; } int delLink(Link_t** link){ //INFO("\n"); Link_t *tLink = *link; Link_t *headLink = tLink->head; Link_t *tailLink = tLink->tail; if(headLink != NULL){ headLink->tail = tailLink; }else{ *link = tailLink; } if(tailLink != NULL){ tailLink->head = headLink; } free(tLink); return 0; } int printLinkInfo(Link_t *link, char *json){ //INFO("\n"); int len = 0; len += sprintf(json + len, "{"); if(link != NULL){ if(link->type == 1){ len += sprintf(json + len, "\"out\": \"%s_%x\", ", link->accelNode->accel.name, link->accelNode->accel.index); len += sprintf(json + len, "\"in\": \"%s_%x\", ", link->buffNode->buffer.name, link->buffNode->buffer.index); } else{ len += sprintf(json + len, "\"out\": \"%s_%x\", ", link->buffNode->buffer.name, link->buffNode->buffer.index); len += sprintf(json + len, "\"in\": \"%s_%x\", ", link->accelNode->accel.name, link->accelNode->accel.index); } len += sprintf(json + len, "\"channel\": \"0x%x\", ", link->channel); len += sprintf(json + len, "\"transactionSize\": \"0x%x\", ", link->transactionSize); len += sprintf(json + len, "\"transactionIndex\": \"0x%x\" ", link->transactionIndex); len += sprintf(json + len, "}"); } return len; } int printLinks(Link_t *link, char *json){ //INFO("\n"); int len = 0; if(link != NULL){ len += printLinkInfo(link, json + len); if(link->tail != NULL){ len += sprintf(json + len, ",\n"); } len += printLinks(link->tail, json + len); } return len; } int printLinksInfo(Link_t *link, char* json){ //INFO("\n"); int len = 0; len += sprintf(json + len, "\"links\":["); len += printLinks(link, json + len); len += sprintf(json + len, "]}\n"); return len; } Schedule_t* createSchedule(DependencyList_t *dependency, int index, int offset, int size, int first, int last){ //, BuffNode_t *dependentBuffNode){ //INFO("\n"); Schedule_t* schedule = (Schedule_t *) malloc(sizeof(Schedule_t)); schedule->index = index; schedule->dependency = dependency; schedule->size = size; schedule->offset = offset; schedule->status = 0; schedule->first = first; schedule->last = last; //schedule->dependentBuffNode = dependentBuffNode; schedule->head = NULL; schedule->tail = NULL; return schedule; } Schedule_t* addSchedule(Schedule_t** schedule, Schedule_t* nextSchedule){ //INFO("\n"); Schedule_t *tschedule = *schedule; if(tschedule != NULL){ while(tschedule->tail != NULL){ tschedule = tschedule->tail; } tschedule->tail = nextSchedule; nextSchedule->head = tschedule; } else{ *schedule = nextSchedule; } return nextSchedule; } int delSchedule(Schedule_t** schedule, Schedule_t** scheduleHead){ Schedule_t *tSchedule = *schedule; Schedule_t *headSchedule = tSchedule->head; Schedule_t *tailSchedule = tSchedule->tail; if(headSchedule != NULL){ *schedule = tailSchedule; headSchedule->tail = tailSchedule; }else{ *schedule = tailSchedule; *scheduleHead = tailSchedule; //INFO("%p\n", *schedule); } if(tailSchedule != NULL){ tailSchedule->head = headSchedule; } free(tSchedule); return 0; } int printSchedule(Schedule_t* schedule){ //INFO("\n"); //char json[1000]; if(schedule != NULL){ while(1){ //printDepend(schedule->dependency); INFOP("%d: %s%d ", schedule->index, schedule->dependency->link->accelNode->accel.name, schedule->dependency->link->accelNode->accel.index); if(schedule->dependency->link->type){ INFOP("====> "); }else{ INFOP("<==== "); } INFOP("%s%d %lx", schedule->dependency->link->buffNode->buffer.name, schedule->dependency->link->buffNode->buffer.index, schedule->dependency->link->buffNode->buffer.phyAddr); //if(schedule->dependentBuffNode){ // INFOP("depends on %s%d\n", // schedule->dependentBuffNode->buffer.name, // schedule->dependentBuffNode->buffer.index); //} //else{ INFOP("\tfirst: %d last: %d\n", schedule->first, schedule->last); //} if(schedule->tail != NULL){ schedule = schedule->tail; } else break; } } return 0; } Link_t* addInputBuffer(AccelNode_t *accelNode, BuffNode_t *buffNode, int offset, int transactionSize, int transactionIndex, int channel){ //INFO("\n"); Link_t* link = (Link_t *) malloc(sizeof(Link_t)); link->accelNode = accelNode; link->buffNode = buffNode; link->transactionSize = transactionSize; link->offset = offset; link->totalTransactionDone = 0; link->totalTransactionScheduled = 0; link->transactionIndex = transactionIndex; link->channel = channel; link->accounted = 0; link->type = 0; link->head = NULL; link->tail = NULL; buffNode->buffer.readerCount += 1; if(accelNode->accel.InterRMCompatible == INTER_RM_COMPATIBLE){ buffNode->buffer.InterRMCompatible += 1; //buffNode->buffer.srcSlot = accelNode->accel.slot; buffNode->buffer.sincSlot = accelNode->accel.slot; } return link; } Link_t* addOutputBuffer(AccelNode_t *accelNode, BuffNode_t *buffNode, int offset, int transactionSize, int transactionIndex, int channel){ //INFO("\n"); Link_t* link = (Link_t *) malloc(sizeof(Link_t)); link->accelNode = accelNode; link->buffNode = buffNode; link->transactionSize = transactionSize; link->offset = offset; link->totalTransactionDone = 0; link->totalTransactionScheduled = 0; link->transactionIndex = transactionIndex; link->channel = channel; link->accounted = 0; link->type = 1; link->head = NULL; link->tail = NULL; //INFO("\n"); // INFO("%p\n", accelNode); //->accel.InterRMCompatible); if(accelNode->accel.InterRMCompatible == INTER_RM_COMPATIBLE && buffNode->buffer.type == 1){ buffNode->buffer.InterRMCompatible += 1; buffNode->buffer.srcSlot = accelNode->accel.slot; //buffNode->buffer.sincSlot = accelNode->accel.slot; } //INFO("\n"); return link; } int updateBuffers(AcapGraph_t* graph, Link_t* linkHead){ Link_t* link = linkHead; Buffers_t* buffers = SIHAGetBuffers(); //INFO("%p\n", buffers); if (link != NULL){ //INFO("%d %s%d %d %d %p %lx\n", link->type, link->buffNode->buffer.name, link->buffNode->buffer.index, link->buffNode->buffer.fd, link->buffNode->buffer.size, link->buffNode->buffer.ptr, link->buffNode->buffer.phyAddr); if(link->buffNode->buffer.type == PL_BASED && link->buffNode->buffer.InterRMCompatible == 2){ //INFO("Buffer Type PL_BASED and InterRMCompatible is enabled\n"); } else if(buffers != NULL && link->type == 0 && link->buffNode->buffer.fd == 0 && link->accelNode->accel.inHardware){ //INFO("IF 1\n");//INFO("%s %d %p\n", link->accelNode->accel.name, link->accelNode->accel.index, link->tail); //INFO("%x : %x\n", link->buffNode->buffer.size, buffers->MM2S_size[link->accelNode->accel.index]); if(link->buffNode->buffer.size == buffers->MM2S_size[link->accelNode->accel.index]){ link->buffNode->buffer.fd = buffers->MM2S_fd [link->accelNode->accel.index]; link->buffNode->buffer.size = buffers->MM2S_size [link->accelNode->accel.index]; link->buffNode->buffer.handle = buffers->MM2S_handle[link->accelNode->accel.index]; link->buffNode->buffer.ptr = buffers->MM2S_ptr [link->accelNode->accel.index]; link->buffNode->buffer.phyAddr = buffers->MM2S_paddr [link->accelNode->accel.index]; } else if(link->buffNode->buffer.size == buffers->config_size[link->accelNode->accel.index]){ link->buffNode->buffer.fd = buffers->config_fd [link->accelNode->accel.index]; link->buffNode->buffer.size = buffers->config_size [link->accelNode->accel.index]; link->buffNode->buffer.handle = buffers->config_handle[link->accelNode->accel.index]; link->buffNode->buffer.ptr = buffers->config_ptr [link->accelNode->accel.index]; link->buffNode->buffer.phyAddr = buffers->config_paddr [link->accelNode->accel.index]; } link->buffNode->buffer.readctr[0] = 0; link->buffNode->buffer.readctr[1] = 0; link->buffNode->buffer.writectr[0] = 0; link->buffNode->buffer.writectr[1] = 0; link->buffNode->buffer.status = EMPTY; link->buffNode->readStatus = 0; //INFO("%s%d %d %d %p %lx\n", link->buffNode->buffer.name, link->buffNode->buffer.index, link->buffNode->buffer.fd, link->buffNode->buffer.size, link->buffNode->buffer.ptr, link->buffNode->buffer.phyAddr); } else if(buffers == NULL && link->type == 0 && link->buffNode->buffer.fd == 0){ //INFO("%s%d %d %d %p %lx\n", link->buffNode->buffer.name, link->buffNode->buffer.index, link->buffNode->buffer.fd, link->buffNode->buffer.size, link->buffNode->buffer.ptr, link->buffNode->buffer.phyAddr); xrt_allocateBuffer(graph->drmfd, link->buffNode->buffer.size, &link->buffNode->buffer.handle, &link->buffNode->buffer.ptr, &link->buffNode->buffer.phyAddr, &link->buffNode->buffer.fd); } //INFO("IF END\n"); if(link->tail != NULL){ updateBuffers(graph, link->tail); } } return 0; } int updateBuffersPass2(AcapGraph_t* graph, Link_t* linkHead){ Link_t* link = linkHead; Buffers_t* buffers = SIHAGetBuffers(); //INFO("\n"); if (link != NULL){ //INFO("##%d\n", link->buffNode->buffer.fd); if(link->buffNode->buffer.type == PL_BASED && link->buffNode->buffer.InterRMCompatible == 2){ } else if(buffers != NULL && link->buffNode->buffer.fd == 0){ //INFO("%s %d %p\n", link->accelNode->accel.name, link->accelNode->accel.index, link->tail); link->buffNode->buffer.fd = buffers->S2MM_fd [link->accelNode->accel.index]; link->buffNode->buffer.size = buffers->S2MM_size [link->accelNode->accel.index]; link->buffNode->buffer.handle = buffers->S2MM_handle[link->accelNode->accel.index]; link->buffNode->buffer.ptr = buffers->S2MM_ptr [link->accelNode->accel.index]; link->buffNode->buffer.phyAddr = buffers->S2MM_paddr [link->accelNode->accel.index]; link->buffNode->buffer.readctr[0] = 0; link->buffNode->buffer.readctr[1] = 0; link->buffNode->buffer.writectr[0] = 0; link->buffNode->buffer.writectr[1] = 0; link->buffNode->buffer.status = EMPTY; link->buffNode->readStatus = 0; //INFO("%s%d %d %d %p %lx\n", link->buffNode->buffer.name, link->buffNode->buffer.index, link->buffNode->buffer.fd, link->buffNode->buffer.size, link->buffNode->buffer.ptr, link->buffNode->buffer.phyAddr); } else if(buffers == NULL && link->buffNode->buffer.fd == 0){ //INFO("%s%d %d %d %p %lx\n", link->buffNode->buffer.name, link->buffNode->buffer.index, link->buffNode->buffer.fd, link->buffNode->buffer.size, link->buffNode->buffer.ptr, link->buffNode->buffer.phyAddr); xrt_allocateBuffer(graph->drmfd, link->buffNode->buffer.size, &link->buffNode->buffer.handle, &link->buffNode->buffer.ptr, &link->buffNode->buffer.phyAddr, &link->buffNode->buffer.fd); } if(link->tail != NULL){ updateBuffersPass2(graph, link->tail); } } return 0; } DependencyList_t* createDependency(Link_t* link){ //INFO("\n"); DependencyList_t* dependency = (DependencyList_t *) malloc(sizeof(DependencyList_t)); dependency->link = link; dependency->linkCount = 0; dependency->head = NULL; dependency->tail = NULL; return dependency; } DependencyList_t* addDependency(DependencyList_t** dependency, DependencyList_t* nextDependency){ //INFO("\n"); DependencyList_t* tdependency = *dependency; if(tdependency != NULL){ while(tdependency->tail != NULL){ tdependency = tdependency->tail; } tdependency->tail = nextDependency; nextDependency->head = tdependency; } else{ *dependency = nextDependency; } return nextDependency; } int delDependency(DependencyList_t** dependency){ //INFO("\n"); DependencyList_t *tDependency = *dependency; DependencyList_t *headDependency = tDependency->head; DependencyList_t *tailDependency = tDependency->tail; if(headDependency != NULL){ headDependency->tail = tailDependency; }else{ *dependency = tailDependency; } if(tailDependency != NULL){ tailDependency->head = headDependency; } free(tDependency); return 0; } int printDepend(DependencyList_t* dependency){ //INFO("%p\n", dependency); char json[1000]; if(dependency != NULL){ printLinkInfo(dependency->link, json); //INFO("link : %s\n",json); for(int i=0; i < dependency->linkCount; i++){ printLinkInfo(dependency->dependentLinks[i], json); //INFO("depends on : %s\n",json); } } return 0; } int printDependency(DependencyList_t* dependency){ //INFO("\n"); //char json[1000]; if(dependency != NULL){ while(1){ //printDepend(dependency); if(dependency->tail != NULL){ dependency = dependency->tail; } else break; } } return 0; } int updateDepend(DependencyList_t** dependencyHead, Link_t* linkHead){ //char json[1000]; Link_t* link = linkHead; DependencyList_t* dependency; DependencyList_t* cDependency = *dependencyHead; while(cDependency != NULL){ link = linkHead; while(link != NULL){ if(link->type == 0 && cDependency->link->type == 1 && cDependency->link->transactionIndex == link->transactionIndex){ cDependency->dependentLinks[cDependency->linkCount] = link; cDependency->linkCount = cDependency->linkCount + 1; } if(link->type == 0 && cDependency->link->type == 1 && cDependency->link->buffNode->buffer.index == link->buffNode->buffer.index){ if(link->accounted == 0){ link->accounted = 1; dependency = createDependency(link); addDependency(dependencyHead, dependency); } } if(link->type == 1 && cDependency->link->type == 0 && cDependency->link->transactionIndex == link->transactionIndex){ cDependency->dependentLinks[cDependency->linkCount] = link; cDependency->linkCount = cDependency->linkCount + 1; if(link->accounted == 0){ link->accounted = 1; dependency = createDependency(link); addDependency(dependencyHead, dependency); } } link = link->tail; } cDependency = cDependency->tail; //INFO("$### : %s\n",json); link = linkHead; } return 0; } int updateDependency(DependencyList_t** dependencyHead, Link_t* linkHead){ //char json[1000]; Link_t* link = linkHead; DependencyList_t* dependency; while(link != NULL){ if(link->accelNode->accel.type == IN_NODE){ dependency = createDependency(link); addDependency(dependencyHead, dependency); } link = link->tail; } updateDepend(dependencyHead, linkHead); printDependency(*dependencyHead); return 0; } int graphSchedule(Schedule_t** scheduleHead, DependencyList_t* dependencyHead){ DependencyList_t* cDependency = dependencyHead; Schedule_t* tSchedule; int tSize, first, last; int pending = 0; int index = 0; //for(int i = 0; i < 3; i++){//)while(1){ while(1){ while(cDependency != NULL){ //INFO("$$$$$$$$$$$$$$$$$$$$##########%d\n", pending); //printDepend(cDependency); tSize = cDependency->link->transactionSize - cDependency->link->totalTransactionScheduled; if(tSize > cDependency->link->buffNode->buffer.size){ tSize = cDependency->link->buffNode->buffer.size; } //INFO("%x %x %x\n", tSize, cDependency->link->transactionSize, cDependency->link->totalTransactionScheduled); if(tSize > 0){ if(cDependency->link->totalTransactionScheduled <= 0){ first = 1; } else{ first = 0; } cDependency->link->totalTransactionScheduled += tSize; if(cDependency->link->transactionSize - cDependency->link->totalTransactionScheduled <= 0){ last = 1; } else{ last = 0; } tSchedule = createSchedule(cDependency, index, cDependency->link->offset, tSize, first, last); index ++; addSchedule(scheduleHead, tSchedule); pending += tSize; //INFO("======== > Scheduled\n"); } cDependency = cDependency->tail; } //INFO("#######################################%d\n", pending); if(pending == 0) break; pending = 0; cDependency = dependencyHead; } printSchedule(*scheduleHead); return 0; } //################################################################################ //################################################################################ // AcapdGraph //################################################################################ AccelNode_t* acapAddAccelNode(AcapGraph_t *acapGraph, char *name, int dmaType, FALLBACKFUNCTION fallbackfunction, int InterRMCompatible, int SchedulerBypassFlag){ //INFO("%d %p %d\n", dmaType, fallbackfunction, InterRMCompatible); AccelNode_t *nextAccel = createAccelNode(name, dmaType, dmaType, fallbackfunction, InterRMCompatible, SchedulerBypassFlag); nextAccel->accel.type = HW_NODE; return addAccelNode(&(acapGraph->accelNodeHead), nextAccel); } AccelNode_t* acapAddAccelNodeForceFallback(AcapGraph_t *acapGraph, char *name, int dmaType, FALLBACKFUNCTION fallbackfunction, int InterRMCompatible, int SchedulerBypassFlag){ //INFO("\n"); AccelNode_t *nextAccel = createAccelNode(name, dmaType, dmaType, fallbackfunction, InterRMCompatible, SchedulerBypassFlag); nextAccel->accel.type = SW_NODE; return addAccelNode(&(acapGraph->accelNodeHead), nextAccel); } int forceFallback(AccelNode_t *accelNode){ //INFO("\n"); accelNode->accel.type = SW_NODE; return 0; } AccelNode_t* acapAddInputNode(AcapGraph_t *acapGraph, uint8_t *buff, int size, int SchedulerBypassFlag, sem_t* semptr){ //INFO("\n"); AccelNode_t *nextAccel = createAccelNode("Input", NONE, NONE, NULL, 0, SchedulerBypassFlag); nextAccel->accel.type = IN_NODE; nextAccel->accel.softBuffer = buff; nextAccel->accel.softBufferSize = size; nextAccel->accel.semptr = semptr; return addAccelNode(&(acapGraph->accelNodeHead), nextAccel); } AccelNode_t* acapAddOutputNode(AcapGraph_t *acapGraph, uint8_t *buff, int size, int SchedulerBypassFlag, sem_t* semptr){ //INFO("\n"); AccelNode_t *nextAccel = createAccelNode("Output", NONE, NONE, NULL, 0, SchedulerBypassFlag); nextAccel->accel.type = OUT_NODE; nextAccel->accel.softBuffer = buff; nextAccel->accel.softBufferSize = size; nextAccel->accel.semptr = semptr; return addAccelNode(&(acapGraph->accelNodeHead), nextAccel); } BuffNode_t* acapAddBuffNode(AcapGraph_t *acapGraph, int size, char *name, int type){ //INFO("\n"); BuffNode_t* nextBuff = createBuffNode(size, name, type); return addBuffNode(&(acapGraph->buffNodeHead), nextBuff); } Link_t *acapAddOutputBuffer(AcapGraph_t *acapGraph, AccelNode_t *accelNode, BuffNode_t *buffNode, int offset, int transactionSize, int transactionIndex, int channel){ //INFO("\n"); Link_t *link = addOutputBuffer(accelNode, buffNode, offset, transactionSize, transactionIndex, channel); addLink(&(acapGraph->linkHead), link); return link; } Link_t *acapAddInputBuffer(AcapGraph_t *acapGraph, AccelNode_t *accelNode, BuffNode_t *buffNode, int offset, int transactionSize, int transactionIndex, int channel){ //INFO("\n"); Link_t *link = addInputBuffer(accelNode, buffNode, offset, transactionSize, transactionIndex, channel); addLink(&(acapGraph->linkHead), link); return link; } int acapGraphToJson(AcapGraph_t *acapGraph){ char *json = (char*) malloc(sizeof(char)*0x4000); int len = 0; //INFO("\n"); FILE *fp; fp = fopen("/home/root/plgraph.json", "w"); len += printAccelNodesInfo(acapGraph->accelNodeHead, json + len); len += printBuffNodesInfo (acapGraph->buffNodeHead, json + len); len += printLinksInfo (acapGraph->linkHead, json + len); //:w //INFO("%s", json); fwrite(json, 1, len, fp); fclose(fp); return 0; } int acapGraphConfig(AcapGraph_t *acapGraph){ //INFO("\n"); //acapGraphToJson(acapGraph); updateBuffers(acapGraph, acapGraph->linkHead); //INFO("updateBuffer done !"); //acapGraphToJson(acapGraph); updateBuffersPass2(acapGraph, acapGraph->linkHead); //INFO("updateBufferPass2 done !"); //acapGraphToJson(acapGraph); updateDependency(&(acapGraph->dependencyHead), acapGraph->linkHead); //INFO("updateDependency done !"); return 0; } int acapGraphSchedule(AcapGraph_t *acapGraph){ //INFO("\n"); graphSchedule(&(acapGraph->scheduleHead), acapGraph->dependencyHead); SchedulerTrigger(acapGraph); SchedulerCompletion(acapGraph); return 0; } AcapGraph_t* acapGraphInit(){ //INFO("\n"); srand(time(NULL)); AcapGraph_t*graph = malloc(sizeof(AcapGraph_t)); SchedulerInit(graph); graph->drmfd = open("/dev/dri/renderD128", O_RDWR); if (graph->drmfd < 0) { return NULL; } return graph; } int acapGraphResetLinks(AcapGraph_t *acapGraph){ SchedulerFinalise(acapGraph); while(acapGraph->scheduleHead != NULL){ delSchedule(&(acapGraph->scheduleHead), &(acapGraph->scheduleHead)); } while(acapGraph->dependencyHead != NULL){ delDependency(&(acapGraph->dependencyHead)); } while(acapGraph->linkHead != NULL){ delLink(&(acapGraph->linkHead)); } return 0; } int acapGraphFinalise(AcapGraph_t *acapGraph){ //INFO("\n"); SchedulerFinalise(acapGraph); //INFO("\n"); while(acapGraph->linkHead != NULL){ delLink(&(acapGraph->linkHead)); } //INFO("\n"); acapGraph->linkHead = NULL; while(acapGraph->buffNodeHead != NULL){ delBuffNode(&(acapGraph->buffNodeHead), acapGraph->drmfd); } //INFO("\n"); acapGraph->buffNodeHead = NULL; while(acapGraph->accelNodeHead != NULL){ delAccelNode(&(acapGraph->accelNodeHead)); } acapGraph->accelNodeHead = NULL; while(acapGraph->dependencyHead != NULL){ delDependency(&(acapGraph->dependencyHead)); } acapGraph->dependencyHead = NULL; //nacapGraphToJson(acapGraph); free(acapGraph); acapGraph = NULL; return 0; } dfx-mgr-xilinx_v2023.2/src/sys/linux/graph/graph.h000066400000000000000000000123571446677152000220720ustar00rootroot00000000000000/* * Copyright (c) 2021, Xilinx Inc. and Contributors. All rights reserved. * * SPDX-License-Identifier: MIT */ #include "layer0/uio.h" #include "layer0/xrtbuffer.h" #include "layer0/dm.h" #include #define DDR_BASED 0 #define PL_BASED 1 #define HW_NODE 0 #define SW_NODE 1 #define IO_NODE 2 #define IN_NODE 3 #define OUT_NODE 4 //dmaTypes #define NONE 0 #define HLSDMA 1 #define HLS_MULTICHANNEL_DMA 2 #define FREE 0 #define BUSY 1 #define BUFF_EMPTY 0 #define BUFF_FULL 1 #define BUFF_BUSY 2 //typedef struct Buffer Buffer_t; typedef struct BuffNode BuffNode_t; typedef struct AccelNode AccelNode_t; typedef struct Link Link_t; typedef struct AcapGraph AcapGraph_t; typedef struct DependencyList DependencyList_t; typedef struct Schedule Schedule_t; typedef struct Scheduler Scheduler_t; // Layer 1 Graph Structures struct AccelNode{ Accel_t accel; // Accel Node Link List structure contains all the Accel nodes int S2MMStatus; int MM2SStatus; int SchedulerBypassFlag; int currentTransactionIndex; struct AccelNode *head; struct AccelNode *tail; }; struct BuffNode{ DFXBuffer_t buffer; // Buffer Node Link List structure contains all the Buffer nodes int status; int readStatus; struct BuffNode *head; struct BuffNode *tail; }; struct Link{// Link(transaction paths) Link List structure contains all the link nodes AccelNode_t *accelNode;// Reference to connected accelerator BuffNode_t *buffNode;// Reference to connected buffer int transactionIndex; int transactionSize; int offset; int totalTransactionDone; int totalTransactionScheduled; int type;// Direction of transfer path MM2S or S2MM int channel; int accounted; struct Link *head; struct Link *tail; }; /*struct DependencyList{ Link_t *S2MMlink; Link_t *MM2Slink; struct DependencyList *head; struct DependencyList *tail; };*/ struct DependencyList{ Link_t *link; Link_t *dependentLinks[10]; int linkCount; struct DependencyList *head; struct DependencyList *tail; }; struct Schedule{ DependencyList_t *dependency; //Link_t *link; int index; int size; int offset; int status; int last; int first; //BuffNode_t *dependentBuffNode[10];// Reference to connected buffer //int buffCount; struct Schedule *head; struct Schedule *tail; }; struct Scheduler{ queue_t* CommandQueue; queue_t* ResponseQueue; pthread_t thread[1]; }; struct AcapGraph{ int drmfd; AccelNode_t *accelNodeHead; BuffNode_t *buffNodeHead; Link_t *linkHead; DependencyList_t *dependencyHead; Schedule_t *scheduleHead; Scheduler_t *scheduler; }; extern AccelNode_t* addAccelNode(AccelNode_t **accelNode, AccelNode_t* nextAccel); extern int forceFallback(AccelNode_t *accelNode); extern int delAccelNode(AccelNode_t** accelNode); extern int printAccelInfo(Accel_t accel, char* json); extern int printAccelNodes(AccelNode_t *accelNode, char* json); extern int printAccelNodesInfo(AccelNode_t *accelNode, char* json); extern BuffNode_t* addBuffNode(BuffNode_t** buffNode, BuffNode_t* nextBuff); extern int delBuffNode(BuffNode_t** buffNode, int drm_fd); extern int printBuffInfo(DFXBuffer_t buffer, char* json); extern int printBuffNodes(BuffNode_t *buffNode, char* json); extern int printBuffNodesInfo(BuffNode_t *buffNode, char* json); extern Link_t* addLink(Link_t** link, Link_t* nextLink); extern int delLink(Link_t** link); extern int printLinkInfo(Link_t *link, char *json); extern int printLinks(Link_t *link, char *json); extern int printLinksInfo(Link_t *link, char* json); extern Link_t* addInputBuffer (AccelNode_t *accelNode, BuffNode_t *buffNode, int offset, int transactionSize, int transactionIndex, int channel); extern Link_t* addOutputBuffer(AccelNode_t *accelNode, BuffNode_t *buffNode, int offset, int transactionSize, int transactionIndex, int channel); //################################################################################ // AcapdGraph //################################################################################ #define DISABLE_SCHEDULER 0 #define ENABLE_SCHEDULER 1 AccelNode_t* acapAddAccelNode(AcapGraph_t *acapGraph, char *name, int dmaType, FALLBACKFUNCTION fallbackfunction, int InterRMCompatible, int SchedulerBypassFlag); AccelNode_t* acapAddAccelNodeForceFallback(AcapGraph_t *acapGraph, char *name, int dmaType, FALLBACKFUNCTION fallbackfunction, int InterRMCompatible, int SchedulerBypassFlag); extern AccelNode_t* acapAddInputNode(AcapGraph_t *acapGraph, uint8_t *buff, int size, int SchedulerBypassFlag, sem_t* semptr); extern AccelNode_t* acapAddOutputNode(AcapGraph_t *acapGraph, uint8_t *buff, int size, int SchedulerBypassFlag, sem_t* semptr); BuffNode_t* acapAddBuffNode(AcapGraph_t *acapGraph, int size, char *name, int type); Link_t *acapAddOutputBuffer(AcapGraph_t *acapGraph, AccelNode_t *accelNode, BuffNode_t *buffNode, int offset, int transactionSize, int transactionIndex, int channel); Link_t *acapAddInputBuffer(AcapGraph_t *acapGraph, AccelNode_t *accelNode, BuffNode_t *buffNode, int offset, int transactionSize, int transactionIndex, int channel); int acapGraphToJson(AcapGraph_t *acapGraph); int acapGraphConfig(AcapGraph_t *acapGraph); int acapGraphSchedule(AcapGraph_t *acapGraph); AcapGraph_t* acapGraphInit(); int acapGraphFinalise(AcapGraph_t *acapGraph); extern int delSchedule(Schedule_t** schedule, Schedule_t** scheduleHead); dfx-mgr-xilinx_v2023.2/src/sys/linux/graph/jobScheduler.c000066400000000000000000000223261446677152000233720ustar00rootroot00000000000000/* * Copyright (c) 2021, Xilinx Inc. and Contributors. All rights reserved. * * SPDX-License-Identifier: MIT */ #include #include #include #include #include #include "graph.h" #include "jobScheduler.h" #include "abstractGraph.h" #include "layer0/queue.h" #include #include #include #include #include "aesFallback.h" #include "aes192Fallback.h" #include "metadata.h" #include "layer0/utils.h" #define GRAPH_SUBMIT 0x30 #define GRAPH_DATA_READY 0x31 #define GRAPH_FINISH 0x32 #define GRAPH_SUBMIT_DONE 0x33 #define GRAPH_FINISH_DONE 0x34 void *jobScheduler_Task(void* carg){ //INFO("\n"); // JobScheduler_t *scheduler = (JobScheduler_t *)carg; Element_t *graphList = NULL; AbstractGraph_t *graph = NULL; queue_t *commandQueue = scheduler->CommandQueue; queue_t *responseQueue = scheduler->ResponseQueue; JobQueueBuffer_t *commandQueueBuffer, *responseQueueBuffer; Json_t* json = malloc(sizeof(Json_t)); Metadata_t *metadata = malloc(sizeof(Metadata_t)); //char jsonfile[100]; char *jsonStr; AcapGraph_t *currentGraph = NULL; Element_t *graphElement; int busy = 0; int enableScheduler = 0; _unused(busy); _unused(enableScheduler); while(1){ usleep(1000); graphList = scheduler->graphList; if((busy == 0) && (queue_size(commandQueue) > 0)){ commandQueueBuffer = queue_dequeue(commandQueue); switch (commandQueueBuffer->type){ case GRAPH_SUBMIT: INFO("processing GRAPH_SUBMIT\n"); graphList = scheduler->graphList; graphElement = searchGraphById(&graphList, commandQueueBuffer->id); graph = (AbstractGraph_t *)(graphElement->node); graph->state = AGRAPH_SCHEDULED; //INFO("AGRAPH_SCHEDULED"); responseQueueBuffer = malloc(sizeof(JobQueueBuffer_t)); responseQueueBuffer->type = GRAPH_SUBMIT_DONE; queue_enqueue(responseQueue, responseQueueBuffer); break; case GRAPH_FINISH: INFO("processing GRAPH_FINISH\n"); graphElement = searchGraphById(&graphList, commandQueueBuffer->id); graph = (AbstractGraph_t *)(graphElement->node); // graph->state = AGRAPH_SCHEDULED; // INFO("AGRAPH_SCHEDULED"); responseQueueBuffer = malloc(sizeof(JobQueueBuffer_t)); responseQueueBuffer->type = GRAPH_FINISH_DONE; queue_enqueue(responseQueue, responseQueueBuffer); break; default: break; } } if(graphList != NULL){ //INFO("%p\n", graphList); graphElement = graphList; while(graphElement != NULL){ if(graphElement!= NULL){ graph = (AbstractGraph_t *)(graphElement->node); if (graph != NULL){ switch (graph->state){ case AGRAPH_SCHEDULED: if(currentGraph != NULL){ break; } currentGraph = acapGraphInit(); //INFO("no of accelerators in this graph are: %d\n", graph->accelCount); Element_t* accelElement = graph->accelNodeHead; while(accelElement != NULL){ AbstractAccelNode_t *abstractAccel = (AbstractAccelNode_t *) accelElement->node; //INFO("%d\n", abstractAccel->id); switch(abstractAccel->type){ case HW_NODE: //INFO("#####################\n"); jsonStr = getAccelMetadata(abstractAccel->name,0); //INFO("%s\n", jsonStr); FALLBACKFUNCTION fallback = NULL; //INFO("%s\n", abstractAccel->name); //INFO("%d\n", strcmp(abstractAccel->name, "FFT4")); //INFO("%d\n", strcmp(abstractAccel->name, "aes128encdec")); //INFO("%d\n", strcmp(abstractAccel->name, "fir_compiler")); if(strcmp(abstractAccel->name, "FFT4") == 0){ INFO("Fallback to SoftFFT\n") fallback = softgFFT; } else if(strcmp(abstractAccel->name, "AES128") == 0){ INFO("Fallback to SoftAES\n") fallback = softgAES128; } else if(strcmp(abstractAccel->name, "AES192") == 0){ fallback = softgAES192; } else if(strcmp(abstractAccel->name, "FIR") == 0){ INFO("Fallback to SoftFIR\n") fallback = softgFIR; } str2json(jsonStr, json); json2meta(json, metadata); //printMeta(metadata); abstractAccel->node = acapAddAccelNode(currentGraph, abstractAccel->name, metadata->DMA_type, fallback, metadata->interRM.compatible, 0);//, //metadata->Input_Channel_Count, //metadata->Output_Channel_Count); //INFO("#####################\n"); break; case IN_NODE: abstractAccel->node = acapAddInputNode(currentGraph, abstractAccel->ptr, abstractAccel->size, 0, abstractAccel->semptr); //SchedulerBypassFlag); break; case OUT_NODE: abstractAccel->node = acapAddOutputNode(currentGraph, abstractAccel->ptr, abstractAccel->size, 0, abstractAccel->semptr); //SchedulerBypassFlag); //abstractAccel->node->accel.semptr = abstractAccel->semptr; break; } accelElement = accelElement->tail; } Element_t* buffElement = graph->buffNodeHead; while(buffElement != NULL){ //INFO("%p", buffElement->node); AbstractBuffNode_t *abstractBuff = (AbstractBuffNode_t *) buffElement->node; //INFO("%p %d %s %d\n", currentGraph, abstractBuff->size, abstractBuff->name, // abstractBuff->type); abstractBuff->node = acapAddBuffNode(currentGraph, abstractBuff->size, abstractBuff->name, abstractBuff->type); buffElement = buffElement->tail; } Element_t* linkElement = graph->linkHead; while(linkElement != NULL){ AbstractLink_t *abstractLink = (AbstractLink_t *) linkElement->node; if(abstractLink->type){ abstractLink->node = acapAddOutputBuffer(currentGraph, abstractLink->accelNode->node, abstractLink->buffNode->node, abstractLink->offset, abstractLink->transactionSize, abstractLink->transactionIndex, abstractLink->channel); } else{ abstractLink->node = acapAddInputBuffer(currentGraph, abstractLink->accelNode->node, abstractLink->buffNode->node, abstractLink->offset, abstractLink->transactionSize, abstractLink->transactionIndex, abstractLink->channel); } linkElement = linkElement->tail; } acapGraphConfig(currentGraph); //INFO("acapGraphConfig \n"); acapGraphToJson(currentGraph); //INFO("acapGraphToJson \n"); acapGraphSchedule(currentGraph); //INFO("acapGraphSchedule \n"); acapGraphFinalise(currentGraph); //INFO("acapGraphFinalise \n"); FILE *fp; char json[] = "{\"nodes\": [], \"buffnodes\": [], \"links\":[]}"; fp = fopen("/home/root/plgraph.json", "w"); fwrite(json, 1, strlen(json), fp); fclose(fp); currentGraph = NULL; graph->state = AGRAPH_INIT; break; case AGRAPH_INIT: break; } graphElement = graphElement->tail; } } else{ //INFO("praphElement : %p", graphElement); } } } } return NULL; } JobScheduler_t * jobSchedulerInit(){ JobScheduler_t *scheduler = malloc(sizeof(JobScheduler_t)); dfx_init(); scheduler->graphList = NULL; scheduler->CommandQueue = malloc(sizeof(queue_t)); scheduler->ResponseQueue = malloc(sizeof(queue_t)); *(scheduler->CommandQueue ) = (queue_t) { malloc(sizeof(void*)*1000), 1000, 0, 0, 0, PTHREAD_MUTEX_INITIALIZER, PTHREAD_COND_INITIALIZER, PTHREAD_COND_INITIALIZER }; *(scheduler->ResponseQueue) = (queue_t) { malloc(sizeof(void*)*1000), 1000, 0, 0, 0, PTHREAD_MUTEX_INITIALIZER, PTHREAD_COND_INITIALIZER, PTHREAD_COND_INITIALIZER }; pthread_create(scheduler->thread , NULL, jobScheduler_Task, scheduler); return scheduler; } int jobSchedulerSubmit(JobScheduler_t *scheduler, Element_t *graphElement){ AbstractGraph_t *graph = (AbstractGraph_t *)(graphElement->node); //INFO("Submitting Graph with ID: %d\n", graph->id); JobQueueBuffer_t *commandBuff, *responseBuff; commandBuff = malloc(sizeof(JobQueueBuffer_t)); commandBuff->type = GRAPH_SUBMIT; commandBuff->id = graph->id; queue_enqueue(scheduler->CommandQueue, commandBuff); while(1){ responseBuff = (JobQueueBuffer_t *)queue_dequeue(scheduler->ResponseQueue); if(responseBuff->type == GRAPH_SUBMIT_DONE) break; } return 0; } int jobSchedulerRemove(JobScheduler_t *scheduler, Element_t *graphElement){ AbstractGraph_t *graph = (AbstractGraph_t *)(graphElement->node); _unused(graph); _unused(scheduler); //INFO("Submitting Graph with ID: %d\n", graph->id); JobQueueBuffer_t *commandBuff, *responseBuff; commandBuff = malloc(sizeof(JobQueueBuffer_t)); commandBuff->type = GRAPH_FINISH; commandBuff->id = graph->id; queue_enqueue(scheduler->CommandQueue, commandBuff); while(1){ responseBuff = (JobQueueBuffer_t *)queue_dequeue(scheduler->ResponseQueue); if(responseBuff->type == GRAPH_FINISH_DONE) break; } return 0; } dfx-mgr-xilinx_v2023.2/src/sys/linux/graph/jobScheduler.h000066400000000000000000000010601446677152000233670ustar00rootroot00000000000000#include typedef struct JobScheduler JobScheduler_t; typedef struct JobQueueBuffer JobQueueBuffer_t; typedef struct queue queue_t; typedef struct Element Element_t; struct JobScheduler{ queue_t* CommandQueue; queue_t* ResponseQueue; pthread_t thread[1]; Element_t *graphList; }; struct JobQueueBuffer{ int type; int id; }; extern JobScheduler_t * jobSchedulerInit(); extern int jobSchedulerSubmit(JobScheduler_t *scheduler, Element_t *graphElement); extern int jobSchedulerRemove(JobScheduler_t *scheduler, Element_t *graphElement); dfx-mgr-xilinx_v2023.2/src/sys/linux/graph/layer0/000077500000000000000000000000001446677152000220045ustar00rootroot00000000000000dfx-mgr-xilinx_v2023.2/src/sys/linux/graph/layer0/CMakeLists.txt000066400000000000000000000013661446677152000245520ustar00rootroot00000000000000add_subdirectory (fallback) add_subdirectory (sihaHLS) add_subdirectory (softIO) collect (PROJECT_LIB_HEADERS shellDriver.h) collect (PROJECT_LIB_HEADERS uiomap.h) collect (PROJECT_LIB_HEADERS queue.h) collect (PROJECT_LIB_HEADERS xrtbuffer.h) collect (PROJECT_LIB_HEADERS dm.h) collect (PROJECT_LIB_HEADERS nodebug.h) #collect (PROJECT_LIB_HEADERS slotManager.h) collect (PROJECT_LIB_HEADERS uio.h) collect (PROJECT_LIB_HEADERS siha.h) collect (PROJECT_LIB_HEADERS utils.h) collect (PROJECT_LIB_SOURCES queue.c) collect (PROJECT_LIB_SOURCES xrtbuffer.c) collect (PROJECT_LIB_SOURCES siha.c) #collect (PROJECT_LIB_SOURCES slotManager.c) collect (PROJECT_LIB_SOURCES uio.c) collect (PROJECT_LIB_SOURCES utils.c) collect (PROJECT_LIB_SOURCES shellDriver.c) dfx-mgr-xilinx_v2023.2/src/sys/linux/graph/layer0/dm.h000066400000000000000000000021201446677152000225500ustar00rootroot00000000000000/* * Copyright (c) 2021, Xilinx Inc. and Contributors. All rights reserved. * * SPDX-License-Identifier: MIT */ //#include "queue.h" #include typedef struct DFXBuffer DFXBuffer_t; typedef struct Accel Accel_t; typedef struct queue queue_t; typedef int (*CONFIG)(void*, Accel_t *accel); //volatile uint8_t*); typedef int (*MM2SSTATUS)(void*); typedef int (*S2MMSTATUS)(void*); typedef int (*MM2SDATA)(void*, DFXBuffer_t*, uint64_t, uint64_t, uint8_t, uint8_t); typedef int (*S2MMDATA)(void*, DFXBuffer_t*, uint64_t, uint64_t, uint8_t); typedef int (*S2MMDONE)(void*, DFXBuffer_t*); typedef int (*MM2SDONE)(void*, DFXBuffer_t*); typedef struct dm{ void* dmstruct; int S2MMChannelStatus; int MM2SChannelStatus; CONFIG config; S2MMSTATUS S2MMStatus; S2MMDATA S2MMData; S2MMDONE S2MMDone; MM2SSTATUS MM2SStatus; MM2SDATA MM2SData; MM2SDONE MM2SDone; queue_t* MM2SCommandQueue; queue_t* MM2SResponseQueue; queue_t* S2MMCommandQueue; queue_t* S2MMResponseQueue; queue_t* CommandQueue; queue_t* ResponseQueue; queue_t* CacheQueue; pthread_t thread[2]; }dm_t; dfx-mgr-xilinx_v2023.2/src/sys/linux/graph/layer0/fallback/000077500000000000000000000000001446677152000235435ustar00rootroot00000000000000dfx-mgr-xilinx_v2023.2/src/sys/linux/graph/layer0/fallback/CMakeLists.txt000066400000000000000000000001241446677152000263000ustar00rootroot00000000000000collect (PROJECT_LIB_HEADERS fallback.h) collect (PROJECT_LIB_SOURCES fallback.c) dfx-mgr-xilinx_v2023.2/src/sys/linux/graph/layer0/fallback/fallback.c000066400000000000000000000114421446677152000254500ustar00rootroot00000000000000/* * Copyright (c) 2021, Xilinx Inc. and Contributors. All rights reserved. * * SPDX-License-Identifier: MIT */ #include #include #include #include #include "fallback.h" #include "../utils.h" #include "../dm.h" #include "../xrtbuffer.h" #include "../uio.h" #include #include int fallback_config(void* dmconfig_a, Accel_t *accel){ fallback_DMConfig_t* dmconfig = (fallback_DMConfig_t*)dmconfig_a; _unused(dmconfig); _unused(accel); //INFO("\n"); //dmconfig->data = base; return 0; } /*int fallback_config(void* dmconfig_a, uint8_t InputChannelCount, uint8_t OutputChannelCount){ fallback_DMConfig_t* dmconfig = (fallback_DMConfig_t*)dmconfig_a; INFO("\n"); dmconfig->InputChannelReq[0] = 0; dmconfig->InputChannelCount = InputChannelCount; dmconfig->OutputChannelReq[0] = 0; dmconfig->OutputChannelCount = OutputChannelCount; return 0; }*/ int fallback_MM2SStatus(void* dmconfig_a){ _unused(dmconfig_a); //INFO("\n"); return 0; } int fallback_S2MMStatus(void* dmconfig_a){ _unused(dmconfig_a); //INFO("\n"); return 0; } int fallback_MM2SData(void* dmconfig_a, DFXBuffer_t* data, uint64_t offset, uint64_t size, uint8_t firstLast, uint8_t tid){ //INFO("\n"); _unused(firstLast); _unused(offset); fallback_DMConfig_t* dmconfig = (fallback_DMConfig_t*)dmconfig_a; dmconfig->InputChannelReq[tid] = (uint8_t*)data->ptr + offset; dmconfig->InputChannelSize[tid] = size; //printf("MM2SData %d : %p %lx\n", tid, data->ptr, data->phyAddr); //printf("%p : %p \n", dmconfig->InputChannelReq[0], dmconfig->OutputChannelReq[0]); if(dmconfig->InputChannelReq[0] != NULL && dmconfig->OutputChannelReq[0] != NULL){ if(dmconfig->fallbackfunction != NULL){ dmconfig->fallbackfunction((void**)dmconfig->InputChannelReq, dmconfig->InputChannelSize, (void**)dmconfig->OutputChannelReq, dmconfig->OutputChannelSize); } dmconfig->MM2Sstatus = 1; dmconfig->S2MMstatus = 1; } if(tid != 0){ dmconfig->MM2Sstatus = 1; } return 0; } int fallback_S2MMData(void* dmconfig_a, DFXBuffer_t* data, uint64_t offset, uint64_t size, uint8_t firstLast){ //INFO("\n"); _unused(offset); _unused(firstLast); fallback_DMConfig_t* dmconfig = (fallback_DMConfig_t*)dmconfig_a; dmconfig->OutputChannelReq[0] = (uint8_t*)data->ptr + offset; dmconfig->OutputChannelSize[0] = size; //printf("S2MMData %p %lx\n", data->ptr, data->phyAddr); //printf("%p : %p \n", dmconfig->InputChannelReq[0], dmconfig->OutputChannelReq[0]); if(dmconfig->InputChannelReq[0] != NULL && dmconfig->OutputChannelReq[0] != NULL){ if(dmconfig->fallbackfunction != NULL){ dmconfig->fallbackfunction((void**)dmconfig->InputChannelReq, dmconfig->InputChannelSize, (void**)dmconfig->OutputChannelReq, dmconfig->OutputChannelSize); } dmconfig->S2MMstatus = 1; dmconfig->MM2Sstatus = 1; } return 0; } int fallback_S2MMDone(void* dmconfig_a, DFXBuffer_t* data){ //INFO("\n"); fallback_DMConfig_t* dmconfig = (fallback_DMConfig_t*)dmconfig_a; _unused(data); int status = dmconfig->S2MMstatus; dmconfig->S2MMstatus = 0; return status; } int fallback_MM2SDone(void* dmconfig_a, DFXBuffer_t* data){ //INFO("\n"); fallback_DMConfig_t* dmconfig = (fallback_DMConfig_t*)dmconfig_a; _unused(data); int status = dmconfig->MM2Sstatus; dmconfig->MM2Sstatus = 0; return status; } int fallback_MM2SAck(void* dmconfig_a){ _unused(dmconfig_a); //INFO("\n"); return 0; } int fallback_S2MMAck(void* dmconfig_a){ //INFO("\n"); _unused(dmconfig_a); return 0; } int fallback_register(dm_t *datamover, uint8_t InputChannelCount, uint8_t OutputChannelCount, FALLBACKFUNCTION fallbackfunction){ //INFO("\n"); datamover->dmstruct = (void*) malloc(sizeof(fallback_DMConfig_t)); datamover->config = fallback_config; datamover->S2MMStatus = fallback_S2MMStatus; datamover->S2MMData = fallback_S2MMData; datamover->S2MMDone = fallback_S2MMDone; datamover->MM2SStatus = fallback_MM2SStatus; datamover->MM2SData = fallback_MM2SData; datamover->MM2SDone = fallback_MM2SDone; fallback_DMConfig_t* dmconfig = (fallback_DMConfig_t*)datamover->dmstruct; dmconfig->InputChannelCount = InputChannelCount; dmconfig->OutputChannelCount = OutputChannelCount; dmconfig->InputChannelReq[0] = NULL; dmconfig->InputChannelReq[1] = NULL; dmconfig->InputChannelReq[2] = NULL; dmconfig->InputChannelReq[3] = NULL; dmconfig->InputChannelReq[4] = NULL; dmconfig->InputChannelReq[5] = NULL; dmconfig->InputChannelReq[6] = NULL; dmconfig->InputChannelReq[7] = NULL; dmconfig->InputChannelReq[8] = NULL; dmconfig->InputChannelReq[9] = NULL; dmconfig->OutputChannelReq[0] = NULL; dmconfig->fallbackfunction = fallbackfunction; dmconfig->S2MMstatus = 0; dmconfig->MM2Sstatus = 0; return 0; } int fallback_unregister(dm_t *datamover){ INFO("\n"); free(datamover->dmstruct); return 0; } dfx-mgr-xilinx_v2023.2/src/sys/linux/graph/layer0/fallback/fallback.h000066400000000000000000000026371446677152000254630ustar00rootroot00000000000000/* * Copyright (c) 2021, Xilinx Inc. and Contributors. All rights reserved. * * SPDX-License-Identifier: MIT */ typedef struct dm dm_t; typedef struct DFXBuffer DFXBuffer_t; typedef struct Accel Accel_t; typedef int (*FALLBACKFUNCTION)(void**, int*, void**, int*); typedef struct fallback_DMConfig{ uint8_t* InputChannelReq[10]; int InputChannelSize[10]; uint8_t InputChannelCount; uint8_t* OutputChannelReq[10]; int OutputChannelSize[10]; uint8_t OutputChannelCount; uint64_t size; uint64_t S2MMstatus; uint64_t MM2Sstatus; FALLBACKFUNCTION fallbackfunction; }fallback_DMConfig_t; extern int fallback_config(void* dmconfig_a, Accel_t *accel); extern int fallback_MM2SStatus(void* dmconfig_a); extern int fallback_S2MMStatus(void* dmconfig_a); extern int fallback_MM2SData(void* dmconfig_a, DFXBuffer_t* data, uint64_t offset, uint64_t size, uint8_t firstLast, uint8_t tid); extern int fallback_S2MMData(void* dmconfig_a, DFXBuffer_t* data, uint64_t offset, uint64_t size, uint8_t firstLast); extern int fallback_S2MMDone(void* dmconfig_a, DFXBuffer_t* data); extern int fallback_MM2SDone(void* dmconfig_a, DFXBuffer_t* data); extern int fallback_MM2SAck(void* dmconfig_a); extern int fallback_S2MMAck(void* dmconfig_a); extern int fallback_register(dm_t *datamover, uint8_t InputChannelCount, uint8_t OutputChannelCount, FALLBACKFUNCTION fallbackfunction); extern int fallback_unregister(dm_t *datamover); dfx-mgr-xilinx_v2023.2/src/sys/linux/graph/layer0/nodebug.h000066400000000000000000000003641446677152000236030ustar00rootroot00000000000000/* * Copyright (c) 2021, Xilinx Inc. and Contributors. All rights reserved. * * SPDX-License-Identifier: MIT */ #define INFO(...) \ fprintf(stderr, " "); #define INFOP(...) \ fprintf(stderr, __VA_ARGS__); #define _unused(x) ((void)(x)) dfx-mgr-xilinx_v2023.2/src/sys/linux/graph/layer0/queue.c000066400000000000000000000023001446677152000232670ustar00rootroot00000000000000/* * Copyright (c) 2021, Xilinx Inc. and Contributors. All rights reserved. * * SPDX-License-Identifier: MIT */ #include #include #include "queue.h" #include #include void queue_enqueue(queue_t *queue, void *value) { pthread_mutex_lock(&(queue->mutex)); while (queue->size == queue->capacity) pthread_cond_wait(&(queue->cond_full), &(queue->mutex)); //printf("enqueue %d\n", *(int *)value); queue->buffer[queue->in] = value; ++ queue->size; ++ queue->in; queue->in %= queue->capacity; pthread_mutex_unlock(&(queue->mutex)); pthread_cond_broadcast(&(queue->cond_empty)); } void *queue_dequeue(queue_t *queue) { pthread_mutex_lock(&(queue->mutex)); while (queue->size == 0) pthread_cond_wait(&(queue->cond_empty), &(queue->mutex)); void *value = queue->buffer[queue->out]; //printf("dequeue %d\n", *(int *)value); -- queue->size; ++ queue->out; queue->out %= queue->capacity; pthread_mutex_unlock(&(queue->mutex)); pthread_cond_broadcast(&(queue->cond_full)); return value; } int queue_size(queue_t *queue) { pthread_mutex_lock(&(queue->mutex)); int size = queue->size; pthread_mutex_unlock(&(queue->mutex)); return size; } dfx-mgr-xilinx_v2023.2/src/sys/linux/graph/layer0/queue.h000066400000000000000000000013511446677152000233010ustar00rootroot00000000000000/* * Copyright (c) 2021, Xilinx Inc. and Contributors. All rights reserved. * * SPDX-License-Identifier: MIT */ #include #include #define QUEUE_INITIALIZER(buffer) { buffer, sizeof(buffer) / sizeof(buffer[0]), 0, 0, 0, PTHREAD_MUTEX_INITIALIZER, PTHREAD_COND_INITIALIZER, PTHREAD_COND_INITIALIZER } typedef struct queue queue_t; struct queue { void **buffer; int capacity; int size; int in; int out; pthread_mutex_t mutex; pthread_cond_t cond_full; pthread_cond_t cond_empty; }; typedef struct biQueue { queue_t *commandQueue; queue_t *responseQueue; } biQueue_t; extern void queue_enqueue(queue_t *queue, void *value); extern void *queue_dequeue(queue_t *queue); extern int queue_size(queue_t *queue); dfx-mgr-xilinx_v2023.2/src/sys/linux/graph/layer0/shellDriver.c000066400000000000000000000036641446677152000244440ustar00rootroot00000000000000/* * Copyright (c) 2021, Xilinx Inc. and Contributors. All rights reserved. * * SPDX-License-Identifier: MIT */ #include #include static volatile uint8_t* SHELLCONFIG; //#define SHELLCONFIG XPAR_STATIC_SHELL_SIHA_MANAGER_0_BASEADDR int configSihaBase(volatile uint8_t* base){ SHELLCONFIG = base; return 0; } int enableSlot(int slot){ switch(slot){ case 0: printf("enabling slot 0 ...\n"); *(uint32_t*)(SHELLCONFIG + 0x4000) = 0x01; *(uint32_t*)(SHELLCONFIG + 0x4004) = 0x01; *(uint32_t*)(SHELLCONFIG + 0x4008) = 0x0b; *(uint32_t*)(SHELLCONFIG + 0x400c) = 0x02; break; case 1: printf("enabling slot 1 ...\n"); *(uint32_t*)(SHELLCONFIG + 0x5000) = 0x01; *(uint32_t*)(SHELLCONFIG + 0x5004) = 0x01; *(uint32_t*)(SHELLCONFIG + 0x5008) = 0x0b; *(uint32_t*)(SHELLCONFIG + 0x500c) = 0x02; break; case 2: printf("enabling slot 2 ...\n"); *(uint32_t*)(SHELLCONFIG + 0x6000) = 0x01; *(uint32_t*)(SHELLCONFIG + 0x6004) = 0x01; *(uint32_t*)(SHELLCONFIG + 0x6008) = 0x0b; *(uint32_t*)(SHELLCONFIG + 0x600c) = 0x02; break; default: break; } return 0; } int disableSlot(int slot){ switch(slot){ case 0: *(uint32_t*)(SHELLCONFIG + 0x4000) = 0x00; *(uint32_t*)(SHELLCONFIG + 0x4004) = 0x00; *(uint32_t*)(SHELLCONFIG + 0x4008) = 0x00; *(uint32_t*)(SHELLCONFIG + 0x400c) = 0x00; printf("disabling slot 0 ...\n"); break; case 1: *(uint32_t*)(SHELLCONFIG + 0x5000) = 0x00; *(uint32_t*)(SHELLCONFIG + 0x5004) = 0x00; *(uint32_t*)(SHELLCONFIG + 0x5008) = 0x00; *(uint32_t*)(SHELLCONFIG + 0x500c) = 0x00; printf("disabling slot 1 ...\n"); break; case 2: *(uint32_t*)(SHELLCONFIG + 0x6000) = 0x00; *(uint32_t*)(SHELLCONFIG + 0x6004) = 0x00; *(uint32_t*)(SHELLCONFIG + 0x6008) = 0x00; *(uint32_t*)(SHELLCONFIG + 0x600c) = 0x00; printf("disabling slot 2 ...\n"); break; default: break; } return 0; } dfx-mgr-xilinx_v2023.2/src/sys/linux/graph/layer0/shellDriver.h000066400000000000000000000003521446677152000244400ustar00rootroot00000000000000/* * Copyright (c) 2021, Xilinx Inc. and Contributors. All rights reserved. * * SPDX-License-Identifier: MIT */ extern int enableSlot(int slot); extern int disableSlot(int slot); extern int configSihaBase(volatile uint8_t* base); dfx-mgr-xilinx_v2023.2/src/sys/linux/graph/layer0/siha.c000066400000000000000000000104111446677152000230710ustar00rootroot00000000000000/* * Copyright (c) 2021, Xilinx Inc. and Contributors. All rights reserved. * * SPDX-License-Identifier: MIT */ #include #include #include #include #include #include #include #include #include #include #include #include "dm.h" #include "shellDriver.h" #include "siha.h" #include "utils.h" #include "uio.h" #include "xrtbuffer.h" #include #include #include static plDevices_t* pldevices=NULL; static Buffers_t* buffers=NULL; static int slotNum[] = {-1, -1, -1}; char slotStr[3][5]; long inthroughput[3], outthroughput[3]; long SIHAGetInThroughput(int slot){ //INFO("\n"); return inthroughput[slot]; } long SIHAGetOutThroughput(int slot){ //INFO("\n"); return outthroughput[slot]; } Buffers_t* SIHAGetBuffers(){ //INFO("\n"); return buffers; } plDevices_t* SIHAGetPLDevices(){ //INFO("\n"); return pldevices; } int SIHAInitAccel(int slot, char * accel){ int status; _unused(accel); slotNum[slot] = load_accelerator(accel); if(slotNum[slot] == -1){ printf("Slot not allocated !!\n"); return -1; } sprintf(slotStr[slot], "%d", slotNum[slot]); if(!pldevices) pldevices = (plDevices_t*) malloc(sizeof(plDevices_t)); pldevices->AccelConfig_fd[slot] = getFD(slotNum[slot], "AccelConfig"); if (pldevices->AccelConfig_fd[slot] < 0){ printf("No AccelConfig dev found\n"); return -1; } pldevices->dma_hls_fd[slot] = getFD(slotNum[slot], "rm_comm_box"); if (pldevices->dma_hls_fd[slot] < 0){ printf("No dma_hls dev found\n"); return -1; } pldevices->slot[slot] = slotNum[slot]; status = mapPlDevicesAccel(pldevices, slot); if (status < 0){ INFO("mapPlDevices Failed !!\n"); return -1; } getRMInfo(); return 0; } int SIHAInit(int configSize, int MM2SSize, int S2MMSize, int slot){ //INFO("\n"); int status; pldevices = (plDevices_t*) malloc(sizeof(plDevices_t)); buffers = (Buffers_t*) malloc(sizeof(Buffers_t)); buffers->config_size[slot] = configSize; buffers->S2MM_size[slot] = S2MMSize; buffers->MM2S_size[slot] = MM2SSize; status = initXrtBuffer(slot, buffers); if (status < 0) { return -1; } status = initPlDevices(pldevices, slot); if (status < 0){ printf("initPlDevices Failed !!\n"); return -1; } status = mapPlDevices(pldevices, slot); if (status < 0){ printf("mapPlDevices Failed !!\n"); return -1; } return 0; } int SIHAStartAccel(int slot){ uint8_t* AccelConfig; AccelConfig = pldevices->AccelConfig[slot]; *(uint32_t*)(AccelConfig) = 0x81; return 0; } int SIHAStopAccel(int slot){ uint8_t* AccelConfig; AccelConfig = pldevices->AccelConfig[slot]; AccelConfig[0] = 0x00; return 0; } int SIHAFinaliseAccel(int slot){ unmapPlDevicesAccel(pldevices, slot); remove_accelerator(slotNum[slot]); getRMInfo(); return 0; } int SIHAFinalise(int slot){ int status; finalisePlDevices(pldevices, slot); status = finaliseXrtBuffer(slot, buffers); if (status < 0) { return -1; } return 0; } int SIHAConfig(int slot, uint32_t* config, int size, int tid){ _unused(tid); memcpy(buffers->config_ptr[slot], (uint8_t*)config, size); printf("%lx : %lx\n", buffers->S2MM_paddr[slot], buffers->MM2S_paddr[slot]); return 0; } int SIHAExchangeBuffer(int slot, uint32_t* inbuff, uint32_t* outbuff, int insize, int outsize){ //INFO("\n"); struct timespec start, finish; double elapsedTime; memcpy(buffers->MM2S_ptr[slot], (uint8_t*)inbuff, insize); //printhex(inbuff, 0x100); //printhex(buffers->MM2S_ptr, 0x100); //printf("%d\n", slot); printf("%lx : %lx\n", buffers->S2MM_paddr[slot], buffers->MM2S_paddr[slot]); clock_gettime(CLOCK_REALTIME, &start); //S2MMData(slot, buffers->S2MM_paddr[slot], outsize); //MM2SData(slot, buffers->MM2S_paddr[slot], insize, 0x00); //while(1){ // if(S2MMDone(slot)) { // printf("S2MM Done !!\n"); // break; // } //} clock_gettime(CLOCK_REALTIME, &finish); elapsedTime = (1.0*(finish.tv_nsec - start.tv_nsec))/1000000000 + finish.tv_sec - start.tv_sec; inthroughput[slot] = (1.0 * insize)/elapsedTime; outthroughput[slot] = (1.0 * outsize)/elapsedTime; //MM2SStatus(slot); //S2MMStatus(slot); //printhex(buffers->S2MM_ptr, 0x100); memcpy((uint8_t*)outbuff, buffers->S2MM_ptr[slot], outsize); return 0; } dfx-mgr-xilinx_v2023.2/src/sys/linux/graph/layer0/siha.h000066400000000000000000000036051446677152000231050ustar00rootroot00000000000000/* * Copyright (c) 2021, Xilinx Inc. and Contributors. All rights reserved. * * SPDX-License-Identifier: MIT */ //#include "xrtbuffer.h" //#include "uio.h" typedef struct Buffers Buffers_t; typedef struct plDevices plDevices_t; typedef struct InBuffer{ uint8_t* buff; } InBuffer_t; typedef struct OutBuffer{ uint8_t* buff; } OutBuffer_t; typedef struct Accelf{ char name[1000]; int allocatedSlot; void* fallbackFunction; uint8_t* confBuffer; InBuffer_t inBuffer[8]; OutBuffer_t outBuffer[7]; int inBufferCount; int outBufferCount; } Accelf_t; typedef struct QueueBufferf{ int type; char filename[1024]; uint8_t* buffer; int transferSize; double throughput; }QueueBufferf_t; #define TASKEND 0x00FF #define STATUS 0x00F0 #define LOOPFILE 0x00F1 #define FFTCONFIG 0x00F2 #define GETFFT 0x00F3 #define BUFFER 0x00F4 #define BUFFERLOOP 0x00F5 #define DONE 0x00F6 extern int SIHAInitAccel(int slot, char * accel); extern int SIHAFinaliseAccel(int slot); extern int SIHAFreeAccel(int slot); extern int SIHAInit(int configSize, int MM2SSize, int S2MMSize, int slot); extern int SIHAFinalise(int slot); extern int SIHAStartAccel(int slot); extern int SIHAStopAccel(int slot); extern int SIHAConfig(int slot, uint32_t* config, int size, int tid); extern int SIHALoopFile(char* filename); extern int SIHAExchangeFile(char* infile, char* outfile); extern int SIHAExchangeBuffer(int slot, uint32_t* inbuff, uint32_t* outbuff, int insize, int outsize); extern void *SIHASendTask(void* carg); extern int SIHATaskInit(); extern int SIHATaskFinalise(); extern int SIHATaskEnd(); extern int SIHA_MM2S_Buffer(uint32_t* inbuff, int insize); extern int SIHA_S2MM_Buffer(uint32_t* outbuff, int outsize); extern int SIHA_S2MM_Completion(); extern long SIHAGetInThroughput(); extern long SIHAGetOutThroughput(); extern Buffers_t* SIHAGetBuffers(); extern plDevices_t* SIHAGetPLDevices(); dfx-mgr-xilinx_v2023.2/src/sys/linux/graph/layer0/sihaHLS/000077500000000000000000000000001446677152000232775ustar00rootroot00000000000000dfx-mgr-xilinx_v2023.2/src/sys/linux/graph/layer0/sihaHLS/CMakeLists.txt000066400000000000000000000001271446677152000260370ustar00rootroot00000000000000collect (PROJECT_LIB_HEADERS sihaHLSdm.h) collect (PROJECT_LIB_SOURCES sihaHLSdm.c) dfx-mgr-xilinx_v2023.2/src/sys/linux/graph/layer0/sihaHLS/sihaHLSdm.c000066400000000000000000000316401446677152000252630ustar00rootroot00000000000000/* * Copyright (c) 2021, Xilinx Inc. and Contributors. All rights reserved. * * SPDX-License-Identifier: MIT */ #include #include #include #include #include "sihaHLSdm.h" #include "../utils.h" #include "../dm.h" #include "../xrtbuffer.h" #include "../uio.h" #include #include //#define DEBUG #include int sihahls_config(void* dmconfig_a, Accel_t *accel){ //volatile uint8_t* base){ sihahls_DMConfig_t* dmconfig = (sihahls_DMConfig_t*)dmconfig_a; dmconfig->s2mm_baseAddr = accel->dma_hls + S2MM; dmconfig->s2mm_APCR = dmconfig->s2mm_baseAddr + APCR; dmconfig->s2mm_GIER = dmconfig->s2mm_baseAddr + GIER; dmconfig->s2mm_IIER = dmconfig->s2mm_baseAddr + IIER; dmconfig->s2mm_IISR = dmconfig->s2mm_baseAddr + IISR; dmconfig->s2mm_ADDR_LOW = dmconfig->s2mm_baseAddr + ADDR_LOW; dmconfig->s2mm_ADDR_HIGH = dmconfig->s2mm_baseAddr + ADDR_HIGH; dmconfig->s2mm_SIZE_LOW = dmconfig->s2mm_baseAddr + SIZE_LOW; dmconfig->s2mm_SIZE_HIGH = dmconfig->s2mm_baseAddr + SIZE_HIGH; dmconfig->s2mm_TID = dmconfig->s2mm_baseAddr + TID; dmconfig->mm2s_baseAddr = accel->dma_hls + MM2S; dmconfig->mm2s_APCR = dmconfig->mm2s_baseAddr + APCR; dmconfig->mm2s_GIER = dmconfig->mm2s_baseAddr + GIER; dmconfig->mm2s_IIER = dmconfig->mm2s_baseAddr + IIER; dmconfig->mm2s_IISR = dmconfig->mm2s_baseAddr + IISR; dmconfig->mm2s_ADDR_LOW = dmconfig->mm2s_baseAddr + ADDR_LOW; dmconfig->mm2s_ADDR_HIGH = dmconfig->mm2s_baseAddr + ADDR_HIGH; dmconfig->mm2s_SIZE_LOW = dmconfig->mm2s_baseAddr + SIZE_LOW; dmconfig->mm2s_SIZE_HIGH = dmconfig->mm2s_baseAddr + SIZE_HIGH; dmconfig->mm2s_TID = dmconfig->mm2s_baseAddr + TID; dmconfig->accel = accel; dmconfig->start = 0; acapd_debug("base Address %x\n",accel->dma_hls); acapd_debug("S2MM %x\n",dmconfig->s2mm_baseAddr); acapd_debug("MM2S %x\n",dmconfig->mm2s_baseAddr); acapd_debug("S2MM %x\n",dmconfig->s2mm_baseAddr + APCR); acapd_debug("MM2S %x\n",dmconfig->mm2s_baseAddr + APCR); return 0; } int sihahls_start(void* dmconfig_a){ sihahls_DMConfig_t* dmconfig = (sihahls_DMConfig_t*)dmconfig_a; INFO("#######################################\n"); int ret;//return 0; //getch(); *(uint32_t*)(dmconfig->accel->AccelConfig) = 0x81; //getch(); switch (dmconfig->accel->slot){ case 0: //ret = system("devmem 0x20100000000 w 0x81"); //*(uint32_t*)(dmconfig->accel->dma_hls + 0x0) = 0x00000000; //*(uint32_t*)(dmconfig->accel->dma_hls + 0x4) = 0x00000002; //*(uint32_t*)(dmconfig->accel->dma_hls + 0x8) = 0x3fffffff; // *(uint32_t*)(dmconfig->accel->dma_hls + 0xC) = 0x00000002; break; case 1: //ret = system("devmem 0x20110000000 w 0x81"); //*(uint32_t*)(dmconfig->accel->dma_hls + 0x0) = 0x80000000; // *(uint32_t*)(dmconfig->accel->dma_hls + 0x4) = 0x00000002; // *(uint32_t*)(dmconfig->accel->dma_hls + 0x8) = 0xbfffffff; //*(uint32_t*)(dmconfig->accel->dma_hls + 0xC) = 0x00000002; break; case 2: //ret = system("devmem 0x20120000000 w 0x81"); //*(uint32_t*)(dmconfig->accel->dma_hls + 0x0) = 0x00000000; //*(uint32_t*)(dmconfig->accel->dma_hls + 0x4) = 0x00000003; //*(uint32_t*)(dmconfig->accel->dma_hls + 0x8) = 0x3fffffff; //*(uint32_t*)(dmconfig->accel->dma_hls + 0xC) = 0x00000003; break; } _unused(ret); dmconfig->start = 1; return 0; } int sihahls_MM2SStatus(void* dmconfig_a){ sihahls_DMConfig_t* dmconfig = (sihahls_DMConfig_t*)dmconfig_a; uint32_t status; //printf("%llx\n", (long long int)ACCELCONFIG[slot]); INFO("\n"); asm volatile("dmb ishld" ::: "memory"); status = *(uint32_t*)(dmconfig->mm2s_APCR); INFOP("################# MM2S %p ls ##############\n", (uint32_t*)(dmconfig->mm2s_baseAddr)); INFOP("ap_start = %x \n", (status >> AP_START) & 0x1); INFOP("ap_done = %x \n", (status >> AP_DONE) & 0x1); INFOP("ap_idle = %x \n", (status >> AP_IDLE) & 0x1); INFOP("ap_ready = %x \n", (status >> AP_READY) & 0x1); INFOP("auto_restart = %x \n", (status >> AP_AUTORESTART) & 0x1); status = *(uint32_t*)(dmconfig->mm2s_GIER); INFOP("GIER = %x \n", status); status = *(uint32_t*)(dmconfig->mm2s_IIER); INFOP("IIER = %x \n", status); status = *(uint32_t*)(dmconfig->mm2s_IISR); INFOP("IISR = %x \n", status); INFOP("@ %x ADDR_LOW = %x \n", MM2S + ADDR_LOW, *(uint32_t*)(dmconfig->mm2s_ADDR_LOW)); INFOP("@ %x ADDR_HIGH = %x \n", MM2S + ADDR_HIGH, *(uint32_t*)(dmconfig->mm2s_ADDR_HIGH)); INFOP("@ %x SIZE_LOW = %x \n", MM2S + SIZE_LOW, *(uint32_t*)(dmconfig->mm2s_SIZE_LOW)); INFOP("@ %x SIZE_HIGH = %x \n", MM2S + SIZE_HIGH, *(uint32_t*)(dmconfig->mm2s_SIZE_HIGH)); INFOP("@ %x TID = %x \n", MM2S + TID, *(uint32_t*)(dmconfig->mm2s_TID)); INFOP("########################################\n"); asm volatile("dmb ishld" ::: "memory"); return 0; } int sihahls_S2MMStatus(void* dmconfig_a){ sihahls_DMConfig_t* dmconfig = (sihahls_DMConfig_t*)dmconfig_a; uint32_t status; INFO("\n"); asm volatile("dmb ishld" ::: "memory"); status = *(uint32_t*)(dmconfig->s2mm_APCR); INFOP("################# S2MM %p ls ###############\n", (uint32_t*)(dmconfig->s2mm_baseAddr)); INFOP("ap_start = %x \n", (status >> AP_START) & 0x1); INFOP("ap_done = %x \n", (status >> AP_DONE) & 0x1); INFOP("ap_idle = %x \n", (status >> AP_IDLE) & 0x1); INFOP("ap_ready = %x \n", (status >> AP_READY) & 0x1); INFOP("auto_restart = %x \n", (status >> AP_AUTORESTART) & 0x1); status = *(uint32_t*)(dmconfig->s2mm_GIER); INFOP("GIER = %x \n", status); status = *(uint32_t*)(dmconfig->s2mm_IIER); INFOP("IIER = %x \n", status); status = *(uint32_t*)(dmconfig->s2mm_IISR); INFOP("IISR = %x \n", status); INFOP("@ %x ADDR_LOW = %x \n", S2MM + ADDR_LOW, *(uint32_t*)(dmconfig->s2mm_ADDR_LOW)); INFOP("@ %x ADDR_HIGH = %x \n", S2MM + ADDR_HIGH, *(uint32_t*)(dmconfig->s2mm_ADDR_HIGH)); INFOP("@ %x SIZE_LOW = %x \n", S2MM + SIZE_LOW, *(uint32_t*)(dmconfig->s2mm_SIZE_LOW)); INFOP("@ %x SIZE_HIGH = %x \n", S2MM + SIZE_HIGH, *(uint32_t*)(dmconfig->s2mm_SIZE_HIGH)); INFOP("@ %x TID = %x \n", S2MM + TID, *(uint32_t*)(dmconfig->s2mm_TID)); INFOP("########################################\n"); asm volatile("dmb ishld" ::: "memory"); return 0; } int sihahls_MM2SData(void* dmconfig_a, uint64_t data, uint64_t size, uint8_t tid){ INFO("\n"); sihahls_DMConfig_t* dmconfig = (sihahls_DMConfig_t*)dmconfig_a; if (dmconfig->start == 0){ sihahls_start(dmconfig_a); } *(uint32_t*)(dmconfig->mm2s_ADDR_LOW) = data & 0xFFFFFFFF; *(uint32_t*)(dmconfig->mm2s_ADDR_HIGH) = (data >> 32) & 0xFFFFFFFF; *(uint32_t*)(dmconfig->mm2s_SIZE_LOW) = (size >> 4) & 0xFFFFFFFF; *(uint32_t*)(dmconfig->mm2s_SIZE_HIGH) = (size >> 36) & 0xFFFFFFFF; *(uint32_t*)(dmconfig->mm2s_TID) = tid; *(uint32_t*)(dmconfig->mm2s_GIER) = 0x1; *(uint32_t*)(dmconfig->mm2s_IIER) = 0x3; *(uint32_t*)(dmconfig->mm2s_APCR) = 0x1 << AP_START; return 0; } int sihahls_S2MMData(void* dmconfig_a, uint64_t data, uint64_t size){ INFO("\n"); sihahls_DMConfig_t* dmconfig = (sihahls_DMConfig_t*)dmconfig_a; if (dmconfig->start == 0){ sihahls_start(dmconfig_a); } *(uint32_t*)(dmconfig->s2mm_ADDR_LOW) = data & 0xFFFFFFFF; *(uint32_t*)(dmconfig->s2mm_ADDR_HIGH) = (data >> 32) & 0xFFFFFFFF; *(uint32_t*)(dmconfig->s2mm_SIZE_LOW) = (size >> 4) & 0xFFFFFFFF; *(uint32_t*)(dmconfig->s2mm_SIZE_HIGH) = (size >> 36) & 0xFFFFFFFF; *(uint32_t*)(dmconfig->s2mm_GIER) = 0x1; *(uint32_t*)(dmconfig->s2mm_IIER) = 0x3; *(uint32_t*)(dmconfig->s2mm_APCR) = 0x1 << AP_START; return 0; } int sihahls_MM2SData_B(void* dmconfig_a, DFXBuffer_t* data, uint64_t offset, uint64_t size, uint8_t firstLast, uint8_t tid){ acapd_debug("MM2S %x\n", MM2S); _unused(firstLast); //INFO("%x %d\n", size, tid); //INFO("%p\n", data->ptr); //printhex((uint32_t*)((uint8_t*)data->ptr + offset), size); //INFO("%x, %x\n", offset, size); sihahls_DMConfig_t* dmconfig = (sihahls_DMConfig_t*)dmconfig_a; //INFO("%d \n", dmconfig->start); if (dmconfig->start == 0){ sihahls_start(dmconfig_a); } uint64_t address = data->phyAddr + offset ; if(data->InterRMCompatible == 2){ acapd_debug("InterRMCompatible"); *(volatile uint32_t*)(dmconfig->mm2s_ADDR_LOW) = data->otherAccel_phyAddr[dmconfig->accel->slot] & 0xFFFFFFFF; *(volatile uint32_t*)(dmconfig->mm2s_ADDR_HIGH) = (data->otherAccel_phyAddr[dmconfig->accel->slot] >> 32) & 0xFFFFFFFF; acapd_debug("ADDR_LOW : %x\n", data->otherAccel_phyAddr[dmconfig->accel->slot] & 0xffffffff); acapd_debug("ADDR_HIGH: %x\n", (data->otherAccel_phyAddr[dmconfig->accel->slot] >> 32) & 0xffffffff); } else{ *(volatile uint32_t*)(dmconfig->mm2s_ADDR_LOW) = address & 0xFFFFFFFF; *(volatile uint32_t*)(dmconfig->mm2s_ADDR_HIGH) = (address >> 32) & 0xFFFFFFFF; acapd_debug("ADDR_LOW : %x\n", address & 0xffffffff); acapd_debug("ADDR_HIGH: %x\n", (address >> 32) & 0xffffffff); } acapd_debug("SIZE_LOW : %x\n", (size >> 4) & 0xffffffff); acapd_debug("SIZE_HIGH: %x\n", (size >> 36) & 0xffffffff); acapd_debug("TID : %x\n", tid); acapd_debug("GIER : %x\n", 0x01); acapd_debug("IIER : %x\n", 0x03); acapd_debug("APCR : %x\n", 0x01 << AP_START); *(volatile uint32_t*)(dmconfig->mm2s_SIZE_LOW) = (size >> 4) & 0xFFFFFFFF; *(volatile uint32_t*)(dmconfig->mm2s_SIZE_HIGH) = (size >> 36) & 0xFFFFFFFF; *(volatile uint32_t*)(dmconfig->mm2s_TID) = tid; *(volatile uint32_t*)(dmconfig->mm2s_GIER) = 0x1; *(volatile uint32_t*)(dmconfig->mm2s_IIER) = 0x3; *(volatile uint32_t*)(dmconfig->mm2s_APCR) = 0x1 << AP_START; return 0; } int sihahls_S2MMData_B(void* dmconfig_a, DFXBuffer_t* data, uint64_t offset, uint64_t size, uint8_t firstLast){ acapd_debug("S2MM %x\n", S2MM); _unused(firstLast); sihahls_DMConfig_t* dmconfig = (sihahls_DMConfig_t*)dmconfig_a; if (dmconfig->start == 0){ sihahls_start(dmconfig_a); } uint64_t address = data->phyAddr + offset ; if(data->InterRMCompatible == 2){ printf("InterRMCompatible"); *(uint32_t*)(dmconfig->s2mm_ADDR_LOW) = data->otherAccel_phyAddr[data->sincSlot] & 0xFFFFFFFF; *(uint32_t*)(dmconfig->s2mm_ADDR_HIGH) = (data->otherAccel_phyAddr[data->sincSlot] >> 32) & 0xFFFFFFFF; acapd_debug("ADDR_LOW : %x\n", data->otherAccel_phyAddr[data->sincSlot] & 0xffffffff); acapd_debug("ADDR_HIGH: %x\n", (data->otherAccel_phyAddr[data->sincSlot] >> 32) & 0xffffffff); } else{ *(uint32_t*)(dmconfig->s2mm_ADDR_LOW) = address & 0xFFFFFFFF; *(uint32_t*)(dmconfig->s2mm_ADDR_HIGH) = (address >> 32) & 0xFFFFFFFF; acapd_debug("ADDR_LOW : %x\n", address & 0xffffffff); acapd_debug("ADDR_HIGH: %x\n", (address >> 32) & 0xffffffff); } acapd_debug("SIZE_LOW : %x\n", (size >> 4) & 0xffffffff); acapd_debug("SIZE_HIGH: %x\n", (size >> 36) & 0xffffffff); acapd_debug("GIER : %x\n", 0x01); acapd_debug("IIER : %x\n", 0x03); acapd_debug("APCR : %x\n", 0x01 << AP_START); *(uint32_t*)(dmconfig->s2mm_SIZE_LOW) = (size >> 4) & 0xFFFFFFFF; *(uint32_t*)(dmconfig->s2mm_SIZE_HIGH) = (size >> 36) & 0xFFFFFFFF; *(uint32_t*)(dmconfig->s2mm_GIER) = 0x1; *(uint32_t*)(dmconfig->s2mm_IIER) = 0x3; *(uint32_t*)(dmconfig->s2mm_APCR) = 0x1 << AP_START; return 0; } int sihahls_S2MMDone(void* dmconfig_a, DFXBuffer_t* data){ sihahls_DMConfig_t* dmconfig = (sihahls_DMConfig_t*)dmconfig_a; int status, res; status = *(uint32_t*)(uint32_t*)(dmconfig->s2mm_APCR); res = status ? ((status >> AP_DONE) | (status >> AP_IDLE)) & 0x1 : 1; acapd_debug("S2MM Status : %x %x\n", status, res); if(res){ data->writeStatus += 1; } //getch(); return res; } int sihahls_MM2SDone(void* dmconfig_a, DFXBuffer_t* data){ sihahls_DMConfig_t* dmconfig = (sihahls_DMConfig_t*)dmconfig_a; int status, res; status = *(volatile uint32_t*)(uint32_t*)(dmconfig->mm2s_APCR); res = status ? ((status >> AP_DONE) | (status >> AP_IDLE)) & 0x1 : 1; acapd_debug("MM2S Status : %x %x\n", status, res); if(res){ data->readStatus += 1; if(data->readStatus == 2*data->readerCount){ data->readStatus = 0; data->writeStatus = 0; } } //getch(); return res; } int sihahls_MM2SAck(void* dmconfig_a){ //INFO("\n"); sihahls_DMConfig_t* dmconfig = (sihahls_DMConfig_t*)dmconfig_a; int status; status = *(uint32_t*)(dmconfig->mm2s_IISR); *(uint32_t*)(dmconfig->mm2s_IISR) = status; return 0; } int sihahls_S2MMAck(void* dmconfig_a){ //INFO("\n"); sihahls_DMConfig_t* dmconfig = (sihahls_DMConfig_t*)dmconfig_a; int status; status = *(uint32_t*)(dmconfig->s2mm_IISR); *(uint32_t*)(dmconfig->s2mm_IISR) = status; return 0; } int sihahls_register(dm_t *datamover){ //INFO("\n"); datamover->dmstruct = (void*) malloc(sizeof(sihahls_DMConfig_t)); datamover->config = sihahls_config; datamover->S2MMStatus = sihahls_S2MMStatus; datamover->S2MMData = sihahls_S2MMData_B; datamover->S2MMDone = sihahls_S2MMDone; datamover->MM2SStatus = sihahls_MM2SStatus; datamover->MM2SData = sihahls_MM2SData_B; datamover->MM2SDone = sihahls_MM2SDone; return 0; } int sihahls_unregister(dm_t *datamover){ //INFO("\n"); free(datamover->dmstruct); return 0; } dfx-mgr-xilinx_v2023.2/src/sys/linux/graph/layer0/sihaHLS/sihaHLSdm.h000066400000000000000000000045411446677152000252700ustar00rootroot00000000000000/* * Copyright (c) 2021, Xilinx Inc. and Contributors. All rights reserved. * * SPDX-License-Identifier: MIT */ typedef struct dm dm_t; typedef struct DFXBuffer DFXBuffer_t; typedef struct Accel Accel_t; // HLS control #define APCR 0x00 #define GIER 0x04 #define IIER 0x08 #define IISR 0x0c #define ADDR_LOW 0x10 #define ADDR_HIGH 0x14 #define SIZE_LOW 0x1c #define SIZE_HIGH 0x20 #define TID 0x24 //Control signals #define AP_START 0 #define AP_DONE 1 #define AP_IDLE 2 #define AP_READY 3 #define AP_AUTORESTART 7 //#define S2MM 0x0000 //#define MM2S 0x8000 //#define S2MM 0x8000 //#define MM2S 0xc000 #define S2MM 0x00000 #define MM2S 0x10000 typedef struct sihahls_DMConfig{ volatile uint8_t* s2mm_baseAddr; volatile uint8_t* s2mm_APCR; volatile uint8_t* s2mm_GIER; volatile uint8_t* s2mm_IIER; volatile uint8_t* s2mm_IISR; volatile uint8_t* s2mm_ADDR_LOW; volatile uint8_t* s2mm_ADDR_HIGH; volatile uint8_t* s2mm_SIZE_LOW; volatile uint8_t* s2mm_SIZE_HIGH; volatile uint8_t* s2mm_TID; volatile uint8_t* mm2s_baseAddr; volatile uint8_t* mm2s_APCR; volatile uint8_t* mm2s_GIER; volatile uint8_t* mm2s_IIER; volatile uint8_t* mm2s_IISR; volatile uint8_t* mm2s_ADDR_LOW; volatile uint8_t* mm2s_ADDR_HIGH; volatile uint8_t* mm2s_SIZE_LOW; volatile uint8_t* mm2s_SIZE_HIGH; volatile uint8_t* mm2s_TID; int start; Accel_t *accel; //int slot; }sihahls_DMConfig_t; extern int sihahls_config(void* dmconfig_a, Accel_t *accel); extern int sihahls_MM2SStatus(void* dmconfig_a); extern int sihahls_S2MMStatus(void* dmconfig_a); extern int sihahls_MM2SData(void* dmconfig_a, uint64_t data, uint64_t size, uint8_t tid); extern int sihahls_S2MMData(void* dmconfig_a, uint64_t data, uint64_t size); extern int sihahls_MM2SData_B(void* dmconfig_a, DFXBuffer_t* data, uint64_t offset, uint64_t size, uint8_t firstLast, uint8_t tid); extern int sihahls_S2MMData_B(void* dmconfig_a, DFXBuffer_t* data, uint64_t offset, uint64_t size, uint8_t firstLast); extern int sihahls_S2MMDone(void* dmconfig_a, DFXBuffer_t* data); extern int sihahls_MM2SDone(void* dmconfig_a, DFXBuffer_t* data); extern int sihahls_MM2SAck(void* dmconfig_a); extern int sihahls_S2MMAck(void* dmconfig_a); extern int sihahls_register(dm_t *datamover); extern int sihahls_unregister(dm_t *datamover); dfx-mgr-xilinx_v2023.2/src/sys/linux/graph/layer0/slotManager.c000066400000000000000000000334341446677152000244330ustar00rootroot00000000000000/* * Copyright (c) 2021, Xilinx Inc. and Contributors. All rights reserved. * * SPDX-License-Identifier: MIT */ #include #include #include #include #include "dm.h" #include "xrtbuffer.h" #include "slotManager.h" #include #include #include "utils.h" void *dm_Task(void* carg){ dm_t *datamover = carg; queue_t *commandQueue = datamover->CommandQueue; queue_t *responseQueue = datamover->ResponseQueue; queue_t *cacheQueue = datamover->CacheQueue; QueueBuffer_t *commandQueueBuffer, *responseQueueBuffer; int res; datamover->S2MMChannelStatus = 0; datamover->MM2SChannelStatus = 0; while(1){ //for(int i=0; i < 1000; i++){ usleep(1000); sleep(1); if(queue_size(commandQueue) > 0 || queue_size(cacheQueue) > 0){ INFO("%d %d\n", queue_size(commandQueue), queue_size(cacheQueue)); if(queue_size(commandQueue) > 0){ commandQueueBuffer = queue_dequeue(commandQueue); } else{ INFO("from Cache Queue !!\n"); commandQueueBuffer = queue_dequeue(cacheQueue); } INFO("%x\n", commandQueueBuffer->type); //printf("%d\n", commandQueueBuffer->type); switch (commandQueueBuffer->type){ case TRANSACTIONEND: INFO("processing TRANSACTIONEND\n"); if(queue_size(commandQueue) <= 1 || queue_size(cacheQueue) == 0){ responseQueueBuffer = malloc(sizeof(QueueBuffer_t)); responseQueueBuffer->type = TRANSACTIONEND; queue_enqueue(responseQueue, responseQueueBuffer); } break; case TASKEND: INFO("processing TASKEND\n"); return NULL; break; case CMATRANSACTION: INFO("processing CMATRANSACTION %s%d %d\n", commandQueueBuffer->buffer->name, commandQueueBuffer->buffer->index, commandQueueBuffer->transferSize); if(commandQueueBuffer->status == 0){ res = -1; if(commandQueueBuffer->direction == TRANS_MM2S && datamover->MM2SChannelStatus == 0){ INFO("Triggering MM2S\n"); res = datamover->MM2SData(datamover->dmstruct, commandQueueBuffer->buffer, commandQueueBuffer->dependentBuffer, commandQueueBuffer->transferSize, 0x00); if(res == 0){ datamover->MM2SChannelStatus = 1; commandQueueBuffer->status = 1; } }else if(commandQueueBuffer->direction == TRANS_S2MM && datamover->S2MMChannelStatus == 0){ INFO("Triggering S2MM\n"); res = datamover->S2MMData(datamover->dmstruct, commandQueueBuffer->buffer, commandQueueBuffer->transferSize); if(res == 0){ datamover->S2MMChannelStatus = 1; commandQueueBuffer->status = 1; } } if(res == -1){INFO("Transaction rescheduled !!\n");} INFO("%d %d\n", queue_size(commandQueue), queue_size(cacheQueue)); queue_enqueue(cacheQueue, commandQueueBuffer); INFO("%d %d\n", queue_size(commandQueue), queue_size(cacheQueue)); } else if(commandQueueBuffer->status == 1){ if(commandQueueBuffer->direction == TRANS_MM2S && datamover->MM2SChannelStatus == 1){ INFO("Status MM2S \n"); if(datamover->MM2SDone(datamover->dmstruct, commandQueueBuffer->buffer)) { INFO("MM2S Done %s%d\n", commandQueueBuffer->buffer->name, commandQueueBuffer->buffer->index); datamover->MM2SChannelStatus = 0; if(commandQueueBuffer->buffer->ptr != NULL){ printhex(commandQueueBuffer->buffer->ptr, 0x20); } responseQueueBuffer = malloc(sizeof(QueueBuffer_t)); responseQueueBuffer->type = DONE; queue_enqueue(responseQueue, responseQueueBuffer); }else { INFO("Transaction rescheduled !!\n"); queue_enqueue(cacheQueue, commandQueueBuffer); } }else if(commandQueueBuffer->direction == TRANS_S2MM && datamover->S2MMChannelStatus == 1){ INFO("Status S2MM \n"); if(datamover->S2MMDone(datamover->dmstruct, commandQueueBuffer->buffer)) { INFO("S2MM Done %s%d\n", commandQueueBuffer->buffer->name, commandQueueBuffer->buffer->index); datamover->S2MMChannelStatus = 0; if(commandQueueBuffer->buffer->ptr != NULL){ printhex(commandQueueBuffer->buffer->ptr, 0x20); } responseQueueBuffer = malloc(sizeof(QueueBuffer_t)); responseQueueBuffer->type = DONE; queue_enqueue(responseQueue, responseQueueBuffer); }else { INFO("Transaction rescheduled !!\n"); queue_enqueue(cacheQueue, commandQueueBuffer); } }else { INFO("Error Occured \n"); } } INFO("%d %d\n", queue_size(commandQueue), queue_size(cacheQueue)); break; default: break; } } } return NULL; } void *MM2S_Task(void* carg){ INFO("\n"); dm_t *datamover = carg; queue_t *commandQueue = datamover->MM2SCommandQueue; queue_t *responseQueue = datamover->MM2SResponseQueue; QueueBuffer_t *commandQueueBuffer, *responseQueueBuffer; int busy = 0; while(1){ //for(int i=0; i < 1000; i++){ usleep(1000); if((busy == 0) && (queue_size(commandQueue) > 0)){ commandQueueBuffer = queue_dequeue(commandQueue); //printf("%d\n", commandQueueBuffer->type); switch (commandQueueBuffer->type){ case TRANSACTIONEND: //INFO("processing TRANSACTIONEND\n"); responseQueueBuffer = malloc(sizeof(QueueBuffer_t)); responseQueueBuffer->type = TRANSACTIONEND; queue_enqueue(responseQueue, responseQueueBuffer); break; case TASKEND: INFO("processing TASKEND\n"); return NULL; break; case CMATRANSACTION: INFO("processing CMATRANSACTION %s%d %d\n", commandQueueBuffer->buffer->name, commandQueueBuffer->buffer->index, commandQueueBuffer->transferSize); datamover->MM2SData(datamover->dmstruct, commandQueueBuffer->buffer, commandQueueBuffer->dependentBuffer, commandQueueBuffer->transferSize, 0x00); //INFO("==============> : %d\n", commandQueueBuffer->buffer->readStatus); busy = 1; break; default: break; } } if (busy){ //datamover->MM2SStatus(datamover->dmstruct); if(datamover->MM2SDone(datamover->dmstruct, commandQueueBuffer->buffer)) { INFO("MM2S Done %s%d\n", commandQueueBuffer->buffer->name, commandQueueBuffer->buffer->index); if(commandQueueBuffer->buffer->readStatus == 2 * commandQueueBuffer->buffer->readerCount){ commandQueueBuffer->buffer->readStatus = 0; commandQueueBuffer->buffer->writeStatus = 0; } busy = 0; if(commandQueueBuffer->buffer->ptr != NULL){ printhex(commandQueueBuffer->buffer->ptr, 0x20); } INFO("==============> : %d\n", commandQueueBuffer->buffer->readStatus); responseQueueBuffer = malloc(sizeof(QueueBuffer_t)); responseQueueBuffer->type = DONE; queue_enqueue(responseQueue, responseQueueBuffer); } } } return NULL; } void *S2MM_Task(void* carg){ INFO("\n"); dm_t *datamover = carg; queue_t *commandQueue = datamover->S2MMCommandQueue; queue_t *responseQueue = datamover->S2MMResponseQueue; QueueBuffer_t *commandQueueBuffer, *responseQueueBuffer; int busy = 0; while(1){ usleep(1000); if((busy ==0) && (queue_size(commandQueue) > 0)){ commandQueueBuffer = queue_dequeue(commandQueue); switch (commandQueueBuffer->type){ case TRANSACTIONEND: //INFO("processing TRANSACTIONEND\n"); responseQueueBuffer = malloc(sizeof(QueueBuffer_t)); responseQueueBuffer->type = TRANSACTIONEND; queue_enqueue(responseQueue, responseQueueBuffer); break; case TASKEND: INFO("processing TASKEND\n"); return NULL; break; case CMATRANSACTION: INFO("processing CMATRANSACTION %s%d %d\n", commandQueueBuffer->buffer->name, commandQueueBuffer->buffer->index, commandQueueBuffer->transferSize); datamover->S2MMData(datamover->dmstruct, commandQueueBuffer->buffer, commandQueueBuffer->transferSize); //INFO("==============> : %d\n", commandQueueBuffer->buffer->writeStatus); busy = 1; break; default: break; } } if (busy){ if(datamover->S2MMDone(datamover->dmstruct, commandQueueBuffer->buffer)) { INFO("S2MM Done %s%d\n", commandQueueBuffer->buffer->name, commandQueueBuffer->buffer->index); if(commandQueueBuffer->buffer->ptr != NULL){ printhex(commandQueueBuffer->buffer->ptr, 0x20); } busy = 0; INFO("==============> : %d\n", commandQueueBuffer->buffer->writeStatus); responseQueueBuffer = malloc(sizeof(QueueBuffer_t)); responseQueueBuffer->type = DONE; queue_enqueue(responseQueue, responseQueueBuffer); } } } return 0; } int TaskInit(dm_t* datamover){ INFO("\n"); datamover->CommandQueue = malloc(sizeof(queue_t)); datamover->ResponseQueue = malloc(sizeof(queue_t)); datamover->CacheQueue = malloc(sizeof(queue_t)); datamover->MM2SCommandQueue = malloc(sizeof(queue_t)); datamover->MM2SResponseQueue = malloc(sizeof(queue_t)); datamover->S2MMCommandQueue = malloc(sizeof(queue_t)); datamover->S2MMResponseQueue = malloc(sizeof(queue_t)); //INFO("%p\n", datamover->S2MMCommandQueue); *(datamover->CommandQueue ) = (queue_t) { malloc(sizeof(void*)*1000), 1000, 0, 0, 0, PTHREAD_MUTEX_INITIALIZER, PTHREAD_COND_INITIALIZER, PTHREAD_COND_INITIALIZER }; *(datamover->ResponseQueue ) = (queue_t) { malloc(sizeof(void*)*1000), 1000, 0, 0, 0, PTHREAD_MUTEX_INITIALIZER, PTHREAD_COND_INITIALIZER, PTHREAD_COND_INITIALIZER }; *(datamover->CacheQueue ) = (queue_t) { malloc(sizeof(void*)*1000), 1000, 0, 0, 0, PTHREAD_MUTEX_INITIALIZER, PTHREAD_COND_INITIALIZER, PTHREAD_COND_INITIALIZER }; *(datamover->MM2SCommandQueue ) = (queue_t) { malloc(sizeof(void*)*1000), 1000, 0, 0, 0, PTHREAD_MUTEX_INITIALIZER, PTHREAD_COND_INITIALIZER, PTHREAD_COND_INITIALIZER }; *(datamover->MM2SResponseQueue) = (queue_t) { malloc(sizeof(void*)*1000), 1000, 0, 0, 0, PTHREAD_MUTEX_INITIALIZER, PTHREAD_COND_INITIALIZER, PTHREAD_COND_INITIALIZER }; *(datamover->S2MMCommandQueue ) = (queue_t) { malloc(sizeof(void*)*1000), 1000, 0, 0, 0, PTHREAD_MUTEX_INITIALIZER, PTHREAD_COND_INITIALIZER, PTHREAD_COND_INITIALIZER }; *(datamover->S2MMResponseQueue) = (queue_t) { malloc(sizeof(void*)*1000), 1000, 0, 0, 0, PTHREAD_MUTEX_INITIALIZER, PTHREAD_COND_INITIALIZER, PTHREAD_COND_INITIALIZER }; //INFO("%p\n", datamover->S2MMCommandQueue); pthread_create(datamover->thread , NULL, dm_Task, datamover); //pthread_create(datamover->thread , NULL, S2MM_Task, datamover); // pthread_create(datamover->thread + 1, NULL, MM2S_Task, datamover); //printf("Thread Started\n"); return 0; } int TaskFinalise(dm_t* datamover){ INFO("\n"); TaskEnd(datamover); pthread_join(datamover->thread[0], NULL); pthread_join(datamover->thread[1], NULL); //printf("Thread Finalised\n"); return 0; } int TaskEnd(dm_t* datamover){ INFO("\n"); QueueBuffer_t *MM2SCommandBuff, *S2MMCommandBuff; MM2SCommandBuff = malloc(sizeof(QueueBuffer_t)); MM2SCommandBuff->type = TASKEND; queue_enqueue(datamover->MM2SCommandQueue, MM2SCommandBuff); S2MMCommandBuff = malloc(sizeof(QueueBuffer_t)); S2MMCommandBuff->type = TASKEND; queue_enqueue(datamover->S2MMCommandQueue, S2MMCommandBuff); return 0; } int transact(dm_t *datamover, Buffer_t* buffer, Buffer_t* dependentBuffer, int insize, int direction){ //INFO("%s%d %x\n", buffer->name, buffer->index, CMATRANSACTION); QueueBuffer_t *commandBuff; commandBuff = malloc(sizeof(QueueBuffer_t)); commandBuff->type = CMATRANSACTION; commandBuff->transferSize = insize; commandBuff->buffer = buffer; commandBuff->dependentBuffer = dependentBuffer; commandBuff->direction = direction; commandBuff->status = 0; buffer->status = INQUEUE; queue_enqueue(datamover->CommandQueue, commandBuff); return 0; } int MM2S_Buffer(dm_t *datamover, Buffer_t* buffer, Buffer_t* dependentBuffer, int insize){ //INFO("%s%d\n", buffer->name, buffer->index); QueueBuffer_t *MM2SCommandBuff; MM2SCommandBuff = malloc(sizeof(*MM2SCommandBuff)); MM2SCommandBuff->type = CMATRANSACTION; MM2SCommandBuff->transferSize = insize; MM2SCommandBuff->buffer = buffer; MM2SCommandBuff->dependentBuffer = dependentBuffer; buffer->status = INQUEUE; queue_enqueue(datamover->MM2SCommandQueue, MM2SCommandBuff); return 0; } int S2MM_Buffer(dm_t *datamover, Buffer_t* buffer, int outsize){ //INFO("%s%d\n", buffer->name, buffer->index); QueueBuffer_t *S2MMCommandBuff; S2MMCommandBuff = malloc(sizeof(*S2MMCommandBuff)); S2MMCommandBuff->type = CMATRANSACTION; S2MMCommandBuff->transferSize = outsize; S2MMCommandBuff->buffer = buffer; buffer->status = INQUEUE; queue_enqueue(datamover->S2MMCommandQueue, S2MMCommandBuff); return 0; } int S2MM_Completion(dm_t *datamover){ //INFO("\n"); QueueBuffer_t *responseQueueBuffer, *commandBuff; commandBuff = malloc(sizeof(QueueBuffer_t)); commandBuff->type = TRANSACTIONEND; queue_enqueue(datamover->CommandQueue, commandBuff); while(1){ //INFO("%d\n",queue_size(datamover->S2MMResponseQueue)) //if(queue_size(datamover->S2MMResponseQueue) > 0){ responseQueueBuffer = queue_dequeue(datamover->ResponseQueue); if(responseQueueBuffer->type == TRANSACTIONEND) break; //} } return 0; } int MM2S_Completion(dm_t *datamover){ //INFO("\n"); QueueBuffer_t *responseQueueBuffer, *commandBuff; commandBuff = malloc(sizeof(QueueBuffer_t)); commandBuff->type = TRANSACTIONEND; queue_enqueue(datamover->CommandQueue, commandBuff); while(1){ //INFO("%d\n",queue_size(datamover->MM2SResponseQueue)) //if(queue_size(datamover->MM2SResponseQueue) > 0){ responseQueueBuffer = queue_dequeue(datamover->ResponseQueue); if(responseQueueBuffer->type == TRANSACTIONEND) break; //} } return 0; } dfx-mgr-xilinx_v2023.2/src/sys/linux/graph/layer0/slotManager.h000066400000000000000000000021571446677152000244360ustar00rootroot00000000000000/* * Copyright (c) 2021, Xilinx Inc. and Contributors. All rights reserved. * * SPDX-License-Identifier: MIT */ //#include "dm.h" #define TASKEND 0x00FF #define STATUS 0x00F0 #define LOOPFILE 0x00F1 #define FFTCONFIG 0x00F2 #define GETFFT 0x00F3 #define BUFFER 0x00F4 #define BUFFERLOOP 0x00F5 #define DONE 0x00F6 #define CMATRANSACTION 0x00F7 #define TRANSACTIONEND 0x00F8 #define TRANS_S2MM 0 #define TRANS_MM2S 1 typedef struct QueueBuffer{ int type; char filename[1024]; Buffer_t* buffer; Buffer_t* dependentBuffer; int direction; int transferSize; double throughput; int status; }QueueBuffer_t; extern int TaskInit(dm_t* datamover); extern int TaskFinalise(dm_t* datamover); extern int TaskEnd(dm_t* datamover); extern int transact(dm_t *datamover, Buffer_t* buffer, Buffer_t* dependentBuffer, int insize, int direction); extern int MM2S_Buffer(dm_t *datamover, Buffer_t* buffer, Buffer_t* dependentBuffer, int insize); extern int S2MM_Buffer(dm_t *datamover, Buffer_t* buffer, int outsize); extern int S2MM_Completion(dm_t *datamover); extern int MM2S_Completion(dm_t *datamover); dfx-mgr-xilinx_v2023.2/src/sys/linux/graph/layer0/softIO/000077500000000000000000000000001446677152000232075ustar00rootroot00000000000000dfx-mgr-xilinx_v2023.2/src/sys/linux/graph/layer0/softIO/CMakeLists.txt000066400000000000000000000001201446677152000257400ustar00rootroot00000000000000collect (PROJECT_LIB_HEADERS softdm.h) collect (PROJECT_LIB_SOURCES softdm.c) dfx-mgr-xilinx_v2023.2/src/sys/linux/graph/layer0/softIO/softdm.c000066400000000000000000000047331446677152000246560ustar00rootroot00000000000000/* * Copyright (c) 2021, Xilinx Inc. and Contributors. All rights reserved. * * SPDX-License-Identifier: MIT */ #include #include #include #include #include "softdm.h" #include "../utils.h" #include "../dm.h" #include "../xrtbuffer.h" #include "../uio.h" #include #include int soft_config(void* dmconfig_a, Accel_t *accel){ //, volatile uint8_t* base){ soft_DMConfig_t* dmconfig = (soft_DMConfig_t*)dmconfig_a; //INFO("%p\n", accel->semptr); dmconfig->data = accel->softBuffer; dmconfig->semptr = accel->semptr; //INFO("%p\n", dmconfig->semptr); return 0; } int soft_MM2SStatus(void* dmconfig_a){ //INFO("\n"); _unused(dmconfig_a); return 0; } int soft_S2MMStatus(void* dmconfig_a){ //INFO("\n"); _unused(dmconfig_a); return 0; } int soft_MM2SData(void* dmconfig_a, DFXBuffer_t* data, uint64_t offset, uint64_t size, uint8_t firstLast, uint8_t tid){ _unused(tid); soft_DMConfig_t* dmconfig = (soft_DMConfig_t*)dmconfig_a; memcpy((uint8_t*)dmconfig->data, ((uint8_t*)data->ptr) + offset, size); if(firstLast){ sem_post(dmconfig->semptr); //INFO("######## Soft MM2SData last #############"); } return 0; } int soft_S2MMData(void* dmconfig_a, DFXBuffer_t* data, uint64_t offset, uint64_t size, uint8_t firstLast){ soft_DMConfig_t* dmconfig = (soft_DMConfig_t*)dmconfig_a; if(firstLast){ //int val; //sem_getvalue (dmconfig->semptr, &val); //INFO("######## Soft S2MMData first #############"); sem_wait(dmconfig->semptr); } memcpy((uint8_t*)data->ptr + offset, (uint8_t*)dmconfig->data, size); return 0; } int soft_S2MMDone(void* dmconfig_a, DFXBuffer_t* data){ _unused(dmconfig_a); _unused(data); return 1; } int soft_MM2SDone(void* dmconfig_a, DFXBuffer_t* data){ _unused(dmconfig_a); _unused(data); return 1; } int soft_MM2SAck(void* dmconfig_a){ //INFO("\n"); _unused(dmconfig_a); return 0; } int soft_S2MMAck(void* dmconfig_a){ //INFO("\n"); _unused(dmconfig_a); return 0; } int soft_register(dm_t *datamover){ //INFO("\n"); datamover->dmstruct = (void*) malloc(sizeof(soft_DMConfig_t)); datamover->config = soft_config; datamover->S2MMStatus = soft_S2MMStatus; datamover->S2MMData = soft_S2MMData; datamover->S2MMDone = soft_S2MMDone; datamover->MM2SStatus = soft_MM2SStatus; datamover->MM2SData = soft_MM2SData; datamover->MM2SDone = soft_MM2SDone; return 0; } int soft_unregister(dm_t *datamover){ //INFO("\n"); free(datamover->dmstruct); return 0; } dfx-mgr-xilinx_v2023.2/src/sys/linux/graph/layer0/softIO/softdm.h000066400000000000000000000020361446677152000246550ustar00rootroot00000000000000/* * Copyright (c) 2021, Xilinx Inc. and Contributors. All rights reserved. * * SPDX-License-Identifier: MIT */ #include typedef struct dm dm_t; typedef struct DFXBuffer DFXBuffer_t; typedef struct Accel Accel_t; typedef struct soft_DMConfig{ uint8_t* data; uint64_t size; sem_t* semptr; }soft_DMConfig_t; extern int soft_config(void* dmconfig_a, Accel_t *accel); //, volatile uint8_t* base); extern int soft_MM2SStatus(void* dmconfig_a); extern int soft_S2MMStatus(void* dmconfig_a); extern int soft_MM2SData(void* dmconfig_a, DFXBuffer_t* data, uint64_t offset, uint64_t size, uint8_t firstLast, uint8_t tid); extern int soft_S2MMData(void* dmconfig_a, DFXBuffer_t* data, uint64_t offset, uint64_t size, uint8_t firstLast); extern int soft_S2MMDone(void* dmconfig_a, DFXBuffer_t* data); extern int soft_MM2SDone(void* dmconfig_a, DFXBuffer_t* data); extern int soft_MM2SAck(void* dmconfig_a); extern int soft_S2MMAck(void* dmconfig_a); extern int soft_register(dm_t *datamover); extern int soft_unregister(dm_t *datamover); dfx-mgr-xilinx_v2023.2/src/sys/linux/graph/layer0/uio.c000066400000000000000000000171661446677152000227570ustar00rootroot00000000000000/* * Copyright (c) 2021, Xilinx Inc. and Contributors. All rights reserved. * * SPDX-License-Identifier: MIT */ #include #include #include #include #include #include #include #include #include #include "uio.h" #include "uiomap.h" #include #include //static plDevices pldevices; int initPlDevices(plDevices_t* pldevices, int slot){ //static plDevices pldevices; //pldevices->clk_wiz_fd = open(DEV_clk_wiz, O_RDWR); //if(pldevices->clk_wiz_fd < 0) return -1; //pldevices->SIHA_Manager_fd = open(DEV_SIHA_Manager, O_RDWR); //if(pldevices->SIHA_Manager_fd < 0) return -1; pldevices->AccelConfig_fd[slot] = open(DEV_AccelConfig[slot], O_RDWR); if(pldevices->AccelConfig_fd[slot] < 0) return -1; pldevices->dma_hls_fd[slot] = open(DEV_dma_hls[slot], O_RDWR); if(pldevices->dma_hls_fd[slot] < 0) return -1; /*switch(slot){ case 0: pldevices->AccelConfig_0_fd = open(DEV_AccelConfig_0, O_RDWR); if(pldevices->AccelConfig_0_fd < 0) return -1; pldevices->dma_hls_0_fd = open(DEV_dma_hls_0, O_RDWR); if(pldevices->dma_hls_0_fd < 0) return -1; //printf("PlDevices openned !!\n", DEV_AccelConfig_0); break; case 1: pldevices->AccelConfig_1_fd = open(DEV_AccelConfig_1, O_RDWR); if(pldevices->AccelConfig_1_fd < 0) return -1; pldevices->dma_hls_1_fd = open(DEV_dma_hls_1, O_RDWR); if(pldevices->dma_hls_1_fd < 0) return -1; break; case 2: pldevices->AccelConfig_2_fd = open(DEV_AccelConfig_2, O_RDWR); if(pldevices->AccelConfig_2_fd < 0) return -1; pldevices->dma_hls_2_fd = open(DEV_dma_hls_2, O_RDWR); if(pldevices->dma_hls_2_fd < 0) return -1; break; }*/ return 0; } int finalisePlDevices(plDevices_t* pldevices, int slot){ //static plDevices pldevices; //close(pldevices->clk_wiz_fd); //close(pldevices->SIHA_Manager_fd); close(pldevices->AccelConfig_fd[slot]); close(pldevices->dma_hls_fd[slot]); /*switch(slot){ case 0: close(pldevices->AccelConfig_0_fd); close(pldevices->dma_hls_0_fd); break; case 1: close(pldevices->AccelConfig_1_fd); close(pldevices->dma_hls_1_fd); break; case 2: close(pldevices->AccelConfig_2_fd); close(pldevices->dma_hls_2_fd); break; }*/ return 0; } int mapPlDevices(plDevices_t* pldevices, int slot){ //pldevices->SIHA_Manager = (uint8_t*) mmap(0, 0x9000, PROT_READ | PROT_WRITE, MAP_SHARED, // pldevices->SIHA_Manager_fd, 0); //if(pldevices->SIHA_Manager == MAP_FAILED){ // printf("Mmap SIHA Manager failed !!\n"); // return -1; //} pldevices->AccelConfig[slot] = (uint8_t*) mmap(0, 0x9000, PROT_READ | PROT_WRITE, MAP_SHARED, pldevices->AccelConfig_fd[slot], 0); if(pldevices->AccelConfig[slot] == MAP_FAILED){ printf("Mmap AccelConfig_0 failed !!\n"); return -1; } pldevices->dma_hls[slot] = (uint8_t*) mmap(0, 0x20000, PROT_READ | PROT_WRITE, MAP_SHARED, pldevices->dma_hls_fd[slot], 0); if(pldevices->dma_hls[slot] == MAP_FAILED){ printf("Mmap dma_hls_0 failed !!\n"); return -1; } /*switch(slot){ case 0: pldevices->AccelConfig_0 = (uint8_t*) mmap(0, 0x9000, PROT_READ | PROT_WRITE, MAP_SHARED, pldevices->AccelConfig_0_fd, 0); if(pldevices->AccelConfig_0 == MAP_FAILED){ printf("Mmap AccelConfig_0 failed !!\n"); return -1; } pldevices->dma_hls_0 = (uint8_t*) mmap(0, 0x10000, PROT_READ | PROT_WRITE, MAP_SHARED, pldevices->dma_hls_0_fd, 0); if(pldevices->dma_hls_0 == MAP_FAILED){ printf("Mmap dma_hls_0 failed !!\n"); return -1; } break; case 1: pldevices->AccelConfig_1 = (uint8_t*) mmap(0, 0x9000, PROT_READ | PROT_WRITE, MAP_SHARED, pldevices->AccelConfig_1_fd, 0); if(pldevices->AccelConfig_1 == MAP_FAILED){ printf("Mmap AccelConfig_1 failed !!\n"); return -1; } pldevices->dma_hls_1 = (uint8_t*) mmap(0, 0x10000, PROT_READ | PROT_WRITE, MAP_SHARED, pldevices->dma_hls_1_fd, 0); if(pldevices->dma_hls_1 == MAP_FAILED){ printf("Mmap dma_hls_1 failed !!\n"); return -1; } break; case 2: pldevices->AccelConfig_2 = (uint8_t*) mmap(0, 0x9000, PROT_READ | PROT_WRITE, MAP_SHARED, pldevices->AccelConfig_2_fd, 0); if(pldevices->AccelConfig_2 == MAP_FAILED){ printf("Mmap AccelConfig_2 failed !!\n"); return -1; } pldevices->dma_hls_2 = (uint8_t*) mmap(0, 0x10000, PROT_READ | PROT_WRITE, MAP_SHARED, pldevices->dma_hls_2_fd, 0); if(pldevices->dma_hls_2 == MAP_FAILED){ printf("Mmap dma_hls_2 failed !!\n"); return -1; } break; }*/ return 0; } int mapPlDevicesAccel(plDevices_t* pldevices, int slot){ pldevices->AccelConfig[slot] = (uint8_t*) mmap(0, 0x9000, PROT_READ | PROT_WRITE, MAP_SHARED, pldevices->AccelConfig_fd[slot], 0); if(pldevices->AccelConfig[slot] == MAP_FAILED){ printf("Mmap AccelConfig_%d failed !!\n", slot); return -1; } pldevices->dma_hls[slot] = (uint8_t*) mmap(0, 0x20000, PROT_READ | PROT_WRITE, MAP_SHARED, pldevices->dma_hls_fd[slot], 0); if(pldevices->dma_hls[slot] == MAP_FAILED){ printf("Mmap dma_hls_%d failed !!\n", slot); return -1; } /*switch(slot){ case 0: pldevices->AccelConfig_0 = (uint8_t*) mmap(0, 0x9000, PROT_READ | PROT_WRITE, MAP_SHARED, pldevices->AccelConfig_0_fd, 0); if(pldevices->AccelConfig_0 == MAP_FAILED){ printf("Mmap AccelConfig_0 failed !!\n"); return -1; } pldevices->dma_hls_0 = (uint8_t*) mmap(0, 0x10000, PROT_READ | PROT_WRITE, MAP_SHARED, pldevices->dma_hls_0_fd, 0); if(pldevices->dma_hls_0 == MAP_FAILED){ printf("Mmap dma_hls_0 failed !!\n"); return -1; } break; case 1: pldevices->AccelConfig_1 = (uint8_t*) mmap(0, 0x9000, PROT_READ | PROT_WRITE, MAP_SHARED, pldevices->AccelConfig_1_fd, 0); if(pldevices->AccelConfig_1 == MAP_FAILED){ printf("Mmap AccelConfig_1 failed !!\n"); return -1; } pldevices->dma_hls_1 = (uint8_t*) mmap(0, 0x10000, PROT_READ | PROT_WRITE, MAP_SHARED, pldevices->dma_hls_1_fd, 0); if(pldevices->dma_hls_1 == MAP_FAILED){ printf("Mmap dma_hls_1 failed !!\n"); return -1; } break; case 2: pldevices->AccelConfig_2 = (uint8_t*) mmap(0, 0x9000, PROT_READ | PROT_WRITE, MAP_SHARED, pldevices->AccelConfig_2_fd, 0); if(pldevices->AccelConfig_2 == MAP_FAILED){ printf("Mmap AccelConfig_2 failed !!\n"); return -1; } pldevices->dma_hls_2 = (uint8_t*) mmap(0, 0x10000, PROT_READ | PROT_WRITE, MAP_SHARED, pldevices->dma_hls_2_fd, 0); if(pldevices->dma_hls_2 == MAP_FAILED){ printf("Mmap dma_hls_2 failed !!\n"); return -1; } break; }*/ return 0; } int unmapPlDevicesAccel(plDevices_t* pldevices, int slot){ munmap(pldevices->AccelConfig[slot], 0x9000); munmap(pldevices->dma_hls[slot], 0x20000); /*switch(slot){ case 0: munmap(pldevices->AccelConfig_0, 0x9000); munmap(pldevices->dma_hls_0, 0x10000); break; case 1: munmap(pldevices->AccelConfig_1, 0x9000); munmap(pldevices->dma_hls_1, 0x10000); break; case 2: munmap(pldevices->AccelConfig_2, 0x9000); munmap(pldevices->dma_hls_2, 0x10000); break; }*/ return 0; } int printPlDevices(plDevices_t* pldevices){ for(int i = 0; i < 10; i ++){ printf("Accel Config %d : %d : %p \n", i, pldevices->AccelConfig_fd[i], pldevices->AccelConfig[i]); printf("DMA HLS %d : %d : %p \n", i, pldevices->dma_hls_fd[i], pldevices->dma_hls[i]); } /*printf("Accel Config 0 : %d\n", pldevices->AccelConfig_0_fd); printf("DMA HLS 0 : %d\n", pldevices->dma_hls_0_fd); printf("Accel Config 1 : %d\n", pldevices->AccelConfig_1_fd); printf("DMA HLS 1 : %d\n", pldevices->dma_hls_1_fd); printf("Accel Config 2 : %d\n", pldevices->AccelConfig_2_fd); printf("DMA HLS 2 : %d\n", pldevices->dma_hls_2_fd);*/ return 0; } dfx-mgr-xilinx_v2023.2/src/sys/linux/graph/layer0/uio.h000066400000000000000000000036231446677152000227550ustar00rootroot00000000000000/* * Copyright (c) 2021, Xilinx Inc. and Contributors. All rights reserved. * * SPDX-License-Identifier: MIT */ #include #include typedef struct dm dm_t; struct plDevices{ //int clk_wiz_fd; //int SIHA_Manager_fd; int slot[20]; int AccelConfig_fd[20]; //int AccelConfig_0_fd; //int AccelConfig_1_fd; //int AccelConfig_2_fd; int dma_hls_fd[20]; //int dma_hls_0_fd; //int dma_hls_1_fd; //int dma_hls_2_fd; //uint8_t* clk_wiz; //uint8_t* SIHA_Manager; uint8_t* AccelConfig[20]; //uint8_t* AccelConfig_0; //uint8_t* AccelConfig_1; //uint8_t* AccelConfig_2; uint8_t* dma_hls[20]; //uint8_t* dma_hls_0; //uint8_t* dma_hls_1; //uint8_t* dma_hls_2; }; typedef struct plDevices plDevices_t; typedef int (*FALLBACKFUNCTION)(void**, int*, void**, int*); #define ACCELDONE 1 #define INTER_RM_COMPATIBLE 1 #define INTER_RM_NOT_COMPATIBLE 0 struct Accel{ char name[1024];// Accelerator name int index; // Serial No of Accelerator int inHardware; // This reg captures the Accel implemented in Hardware int type; // int inDmaType; // Inward Data Mover Type int outDmaType; // Outward Data Mover Type FALLBACKFUNCTION fallbackfunction;// Pointer to a software fallback function int AccelConfig_fd; int dma_hls_fd; int accels_fd[10]; uint8_t* AccelConfig; uint8_t* dma_hls; uint8_t* accels[10]; int slot; int InterRMCompatible; int SchedulerBypassFlag; uint8_t* confBuffer; uint8_t* softBuffer; uint64_t softBufferSize; sem_t* semptr; uint64_t status; dm_t* datamover; }; typedef struct Accel Accel_t; extern int initPlDevices(plDevices_t* pldevices, int slot); extern int finalisePlDevices(plDevices_t* pldevices, int slot); extern int mapPlDevices(plDevices_t* pldevices, int slot); extern int mapPlDevicesAccel(plDevices_t* pldevices, int slot); extern int unmapPlDevicesAccel(plDevices_t* pldevices, int slot); extern int printPlDevices(plDevices_t* pldevices); dfx-mgr-xilinx_v2023.2/src/sys/linux/graph/layer0/uiomap.h000066400000000000000000000010621446677152000234460ustar00rootroot00000000000000/* * Copyright (c) 2021, Xilinx Inc. and Contributors. All rights reserved. * * SPDX-License-Identifier: MIT */ #define DEV_clk_wiz "/dev/uio10" #define DEV_SIHA_Manager "/dev/uio11" //#define DEV_AccelConfig_0 "/dev/uio4" //#define DEV_dma_hls_0 "/dev/uio5" //#define DEV_AccelConfig_1 "/dev/uio6" //#define DEV_dma_hls_1 "/dev/uio7" //#define DEV_AccelConfig_2 "/dev/uio8" //#define DEV_dma_hls_2 "/dev/uio9" const char * DEV_AccelConfig[]={"/dev/uio4", "/dev/uio6", "/dev/uio8"}; const char * DEV_dma_hls[]= {"/dev/uio5", "/dev/uio7", "/dev/uio9"}; dfx-mgr-xilinx_v2023.2/src/sys/linux/graph/layer0/utils.c000066400000000000000000000015571446677152000233200ustar00rootroot00000000000000/* * Copyright (c) 2021, Xilinx Inc. and Contributors. All rights reserved. * * SPDX-License-Identifier: MIT */ #include #include #include #include int compare(int counts, uint32_t *address, uint32_t *reference){ int i; int error = 0; uint32_t value; for (i = 0; i < counts >> 2; i++){ value = *(address + i); if (value != reference[i]){ printf("\n %x != %x Error: Doesn't matched with the reference !!!!\n", value, reference[i]); error = 1; break; } } if (error==0){ printf("\n Success: Matched with the reference !!!!\n"); } printf("\n"); return 0; } // prints string as hex void printhex(uint32_t* data, uint32_t len) { uint32_t i; for (i = 0; i < len >> 2; ++i){ if(i%4==0) fprintf(stderr, "\n%.8x: ", i << 2); fprintf(stderr, "0x%.8x, ", data[i]); } fprintf(stderr, "\n"); } dfx-mgr-xilinx_v2023.2/src/sys/linux/graph/layer0/utils.h000066400000000000000000000003601446677152000233140ustar00rootroot00000000000000/* * Copyright (c) 2021, Xilinx Inc. and Contributors. All rights reserved. * * SPDX-License-Identifier: MIT */ extern int compare(int counts, uint32_t *address, uint32_t *reference); extern void printhex(uint32_t* data, uint32_t len); dfx-mgr-xilinx_v2023.2/src/sys/linux/graph/layer0/xrtbuffer.c000066400000000000000000000113261446677152000241620ustar00rootroot00000000000000/* * Copyright (c) 2021, Xilinx Inc. and Contributors. All rights reserved. * * SPDX-License-Identifier: MIT */ #include #include #include #include #include #include #include #include "zynq_ioctl.h" #include #include "uio.h" #include "xrtbuffer.h" #include #include #include //static plDevices pldevices; //static Buffers buffers; //static int slot = 0; int xrt_allocateBuffer(int drm_fd, int size, int* handle, uint8_t** ptr, unsigned long* paddr, int* fd){ _unused(drm_fd); acapd_buffer_t *acapdBuff = sys_alloc_buffer(size); *handle = acapdBuff->handle; *fd = acapdBuff->fd; *paddr = acapdBuff->PA; *ptr = mmap(0, size, PROT_READ | PROT_WRITE, MAP_SHARED, *fd, 0); /*struct drm_zocl_create_bo info1 = {size, 0xffffffff, DRM_ZOCL_BO_FLAGS_COHERENT | DRM_ZOCL_BO_FLAGS_CMA}; int result = ioctl(drm_fd, DRM_IOCTL_ZOCL_CREATE_BO, &info1); *handle = info1.handle; struct drm_zocl_info_bo infoInfo1 = {info1.handle, 0, 0}; result = ioctl(drm_fd, DRM_IOCTL_ZOCL_INFO_BO, &infoInfo1); if(result < 0){ printf( "error @ drm_zocl_info_bo\n"); return result; } struct drm_zocl_map_bo mapInfo1 = {info1.handle, 0, 0}; result = ioctl(drm_fd, DRM_IOCTL_ZOCL_MAP_BO, &mapInfo1); if(result < 0){ printf( "error @ drm_zocl_map_bo\n"); return result; } *ptr = mmap(0, info1.size, PROT_READ | PROT_WRITE, MAP_SHARED, drm_fd, mapInfo1.offset); *paddr = infoInfo1.paddr; printf("%lx\n", infoInfo1.paddr); struct drm_prime_handle bo_h = {info1.handle, DRM_RDWR, -1}; if (ioctl(drm_fd, DRM_IOCTL_PRIME_HANDLE_TO_FD, &bo_h) < 0) { printf("%s:DRM_IOCTL_PRIME_HANDLE_TO_FD failed:\n", __func__); return -1; } INFO("\n"); *fd = bo_h.fd;*/ return 0; } int xrt_deallocateBuffer(int drm_fd, int size, int *handle, uint8_t** ptr, unsigned long* paddr){ _unused(drm_fd); _unused(handle); munmap(*ptr, size); sys_free_buffer(*paddr); /* struct drm_gem_close closeInfo = {0, 0}; closeInfo.handle = *handle; int result = ioctl(drm_fd, DRM_IOCTL_GEM_CLOSE, &closeInfo); if(result < 0){ printf( "error @ close handle\n"); return result; } *handle = -1; INFO("%d\n", result);*/ return 0; } int mapBuffer(int fd, int size, uint8_t** ptr){ *ptr = mmap(0, size, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0); //INFO("%p \n", *ptr); return 0; } int unmapBuffer(int fd, int size, uint8_t** ptr){ munmap(*ptr, size); *ptr = NULL; close(fd); return 0; } int initXrtBuffer(int slot, Buffers_t* buffers){ int status; if(!buffers->fd){ buffers->fd = open("/dev/dri/renderD128", O_RDWR); if (buffers->fd < 0) { return -1; } } int tmpfd; status = xrt_allocateBuffer(buffers->fd, buffers->config_size[slot], &buffers->config_handle[slot], &buffers->config_ptr[slot], &buffers->config_paddr[slot], &tmpfd); if(status < 0){ printf( "error @ config allocation\n"); return status; } status = xrt_allocateBuffer(buffers->fd, buffers->S2MM_size[slot], &buffers->S2MM_handle[slot], &buffers->S2MM_ptr[slot], &buffers->S2MM_paddr[slot], &tmpfd); if(status < 0){ printf( "error @ S2MM allocation\n"); return status; } status = xrt_allocateBuffer(buffers->fd, buffers->MM2S_size[slot], &buffers->MM2S_handle[slot], &buffers->MM2S_ptr[slot], &buffers->MM2S_paddr[slot], &tmpfd); if(status < 0){ printf( "error @ MM2S allocation\n"); return status; } return 0; } int unallocateBuffer(int fd, int handle){ struct drm_gem_close closeInfo = {handle, 0}; int result = ioctl(fd, DRM_IOCTL_GEM_CLOSE, &closeInfo); if(result < 0){ printf( "error @ close handle\n"); return result; } return 0; } int printBuffer(Buffers_t* buffers, int slot){ INFO("slot : %d\n", slot); INFO("Buffers->config_ptr[slot] : %p\n", buffers->config_ptr[slot]); INFO("Buffers->S2MM_ptr[slot] : %p\n", buffers->S2MM_ptr[slot]); INFO("Buffers->MM2S_ptr[slot] : %p\n", buffers->MM2S_ptr[slot]); _unused(buffers); _unused(slot); return 0; } int finaliseXrtBuffer(int slot, Buffers_t* buffers){ int status; status = unallocateBuffer(buffers->fd, buffers->config_handle[slot]); if(status < 0){ printf( "error @ config\n"); return status; } status = unallocateBuffer(buffers->fd, buffers->S2MM_handle[slot]); if(status < 0){ printf( "error @ S2MM\n"); return status; } status = unallocateBuffer(buffers->fd, buffers->MM2S_handle[slot]); if(status < 0){ printf( "error @ MM2S\n"); return status; } if(buffers->fd && (! buffers->config_handle[2]) && (! buffers->config_handle[1]) && (! buffers->config_handle[2])){ status = close(buffers->fd); if(status < 0){ printf( "error @ FD Close\n"); return status; } } return 0; } dfx-mgr-xilinx_v2023.2/src/sys/linux/graph/layer0/xrtbuffer.h000066400000000000000000000040051446677152000241630ustar00rootroot00000000000000/* * Copyright (c) 2021, Xilinx Inc. and Contributors. All rights reserved. * * SPDX-License-Identifier: MIT */ // xrtbuffer.h #ifndef XRTBUFFER_H #define XRTBUFFER_H #ifdef __cplusplus extern "C" { #endif #include struct Buffers{ int fd; int config_fd[20]; int config_size[20]; int config_handle[20]; int config_used[20]; uint8_t* config_ptr[20]; unsigned long config_paddr[20]; int S2MM_fd[20]; int S2MM_size[20]; int S2MM_handle[20]; int S2MM_used[20]; uint8_t* S2MM_ptr[20]; unsigned long S2MM_paddr[20]; int MM2S_fd[20]; int MM2S_size[20]; int MM2S_handle[20]; int MM2S_used[20]; uint8_t* MM2S_ptr[20]; unsigned long MM2S_paddr[20]; }; typedef struct Buffers Buffers_t; #define EMPTY 0 #define INQUEUE 1 #define FULL 2 struct DFXBuffer{ int index; // Serial No of Buffer int type; // int fd; // File descriptor from ACAPD int size; // Buffer Size int handle;// Buffer XRT Handeler uint8_t* ptr; // Buffer Ptr unsigned long phyAddr; // Buffer Physical Address int srcSlot; // Buffer Physical Address int sincSlot; // Buffer Physical Address unsigned long otherAccel_phyAddr[3]; // Buffer Physical Address int InterRMCompatible; // Buffer Physical Address unsigned int readctr[2]; unsigned int writectr[2]; unsigned int readerCount; unsigned int readStatus; unsigned int writeStatus; unsigned int status; char name[1024]; // Buffer Name Identifier }; typedef struct DFXBuffer DFXBuffer_t; extern int printBuffer(Buffers_t* buffers, int slot); extern int initXrtBuffer(int slot, Buffers_t* buffers); extern int initXrtBuffer(int slot, Buffers_t* buffers); extern int finaliseXrtBuffer(int slot, Buffers_t* buffers); extern int mapBuffer(int fd, int size, uint8_t** ptr); extern int unmapBuffer(int fd, int size, uint8_t** ptr); extern int xrt_allocateBuffer(int drm_fd, int size, int* handle, uint8_t** ptr, unsigned long* paddr, int* fd); extern int xrt_deallocateBuffer(int drm_fd, int size, int *handle, uint8_t** ptr, unsigned long* paddr); #ifdef __cplusplus } #endif #endif dfx-mgr-xilinx_v2023.2/src/sys/linux/graph/metadata.c000066400000000000000000000531171446677152000225430ustar00rootroot00000000000000/* * Copyright (c) 2021, Xilinx Inc. and Contributors. All rights reserved. * * SPDX-License-Identifier: MIT */ #include #include #include #include "metadata.h" #include "graph.h" #define JSMN_PARENT_LINKS #define JSMN_HEADER #include #include "abstractGraph.h" #include #include //#include "uio.h" static int jsoneq(const char *json, jsmntok_t *tok, const char *s) { if (tok->type == JSMN_STRING && (int)strlen(s) == tok->end - tok->start && strncmp(json + tok->start, s, tok->end - tok->start) == 0) { return 0; } return -1; } int json2fallback(Json_t* json, Metadata_t *metadata){ jsmn_parser p; jsmntok_t t[128]; /* We expect no more than 128 tokens */ jsmn_init(&p); int r = jsmn_parse(&p, json->data, json->size, t, sizeof(t) / sizeof(t[0])); if (r < 0) { printf("Failed to parse JSON: %d\n", r); return 1; } /* Assume the top-level element is an object */ if (r < 1 || t[0].type != JSMN_OBJECT) { printf("Object expected\n"); return 1; } for (int i = 1; i < r; i++) { if (jsoneq(json->data, &t[i], "Behaviour") == 0) { sscanf(json->data + t[i + 1].start, "0x%x", &(metadata->fallback.behaviour)); i++; } else if (jsoneq(json->data, &t[i], "fallback_Lib") == 0) { sprintf(metadata->fallback.lib, "%.*s", t[i + 1].end - t[i + 1].start, json->data + t[i + 1].start); i++; } } return 0; } int json2interrm(Json_t* json, Metadata_t *metadata){ jsmn_parser p; jsmntok_t t[128]; /* We expect no more than 128 tokens */ jsmn_init(&p); int r = jsmn_parse(&p, json->data, json->size, t, sizeof(t) / sizeof(t[0])); if (r < 0) { printf("Failed to parse JSON: %d\n", r); return 1; } /* Assume the top-level element is an object */ if (r < 1 || t[0].type != JSMN_OBJECT) { printf("Object expected\n"); return 1; } for (int i = 1; i < r; i++) { if (jsoneq(json->data, &t[i], "Compatible") == 0) { //INFO("%.*s\n", t[i + 1].end - t[i + 1].start, // json->data + t[i + 1].start); //INFO("################# %d\n", strcmp(json->data + t[i + 1].start, "True")); if (strcmp(json->data + t[i + 1].start, "True") > 0){ //INFO("################# %d\n", strcmp(json->data + t[i + 1].start, "True")); metadata->interRM.compatible = INTER_RM_COMPATIBLE; } else{ metadata->interRM.compatible = INTER_RM_NOT_COMPATIBLE; } i++; } if (jsoneq(json->data, &t[i], "Address") == 0) { sscanf(json->data + t[i + 1].start, "0x%lx", &(metadata->interRM.address)); i++; } } return 0; } int json2metadata(Json_t* json, Metadata_t *metadata){ jsmn_parser p; jsmntok_t t[128]; /* We expect no more than 128 tokens */ jsmn_init(&p); int r = jsmn_parse(&p, json->data, json->size, t, sizeof(t) / sizeof(t[0])); if (r < 0) { printf("Failed to parse JSON: %d\n", r); return 1; } /* Assume the top-level element is an object */ if (r < 1 || t[0].type != JSMN_OBJECT) { printf("Object expected\n"); return 1; } for (int i = 1; i < r; i++) { if (jsoneq(json->data, &t[i], "fallback") == 0) { //printf("%.*s\n", t[i + 1].end - t[i + 1].start, // json->data + t[i + 1].start); Json_t* subJson = malloc(sizeof(Json_t)); subJson->data = json->data + t[i + 1].start; subJson->size = t[i + 1].end - t[i + 1].start; json2fallback(subJson, metadata); i++; } else if (jsoneq(json->data, &t[i], "Input_Data_Block_Size") == 0) { //printf("%.*s\n", t[i + 1].end - t[i + 1].start, // json->data + t[i + 1].start); sscanf(json->data + t[i + 1].start, "0x%lx", &(metadata->Input_Data_Block_Size)); i++; } else if (jsoneq(json->data, &t[i], "Output_Data_Block_Size") == 0) { //printf("%.*s\n", t[i + 1].end - t[i + 1].start, // json->data + t[i + 1].start); sscanf(json->data + t[i + 1].start, "0x%lx", &(metadata->Output_Data_Block_Size)); i++; } else if (jsoneq(json->data, &t[i], "Input_Channel_Count") == 0) { //printf("%.*s\n", t[i + 1].end - t[i + 1].start, // json->data + t[i + 1].start); sscanf(json->data + t[i + 1].start, "%hhd", &(metadata->Input_Channel_Count)); i++; } else if (jsoneq(json->data, &t[i], "Output_Channel_Count") == 0) { //printf("%.*s\n", t[i + 1].end - t[i + 1].start, // json->data + t[i + 1].start); sscanf(json->data + t[i + 1].start, "%hhd", &(metadata->Output_Channel_Count)); i++; } else if (jsoneq(json->data, &t[i], "Inter_RM") == 0) { //printf("%.*s\n", t[i + 1].end - t[i + 1].start, // json->data + t[i + 1].start); Json_t* subJson = malloc(sizeof(Json_t)); subJson->data = json->data + t[i + 1].start; subJson->size = t[i + 1].end - t[i + 1].start; json2interrm(subJson, metadata); i++; } else if (jsoneq(json->data, &t[i], "Config_Buffer_Size") == 0) { //printf("%.*s\n", t[i + 1].end - t[i + 1].start, // json->data + t[i + 1].start); sscanf(json->data + t[i + 1].start, "0x%lx", &(metadata->Config_Buffer_Size)); i++; } else if (jsoneq(json->data, &t[i], "Input_Buffer_Size") == 0) { //printf("%.*s\n", t[i + 1].end - t[i + 1].start, // json->data + t[i + 1].start); sscanf(json->data + t[i + 1].start, "0x%lx", &(metadata->Input_Buffer_Size)); i++; } else if (jsoneq(json->data, &t[i], "Output_Buffer_Size") == 0) { //printf("%.*s\n", t[i + 1].end - t[i + 1].start, // json->data + t[i + 1].start); sscanf(json->data + t[i + 1].start, "0x%lx", &(metadata->Output_Buffer_Size)); i++; } else if (jsoneq(json->data, &t[i], "Throughput") == 0) { //printf("%.*s\n", t[i + 1].end - t[i + 1].start, // json->data + t[i + 1].start); sscanf(json->data + t[i + 1].start, "%ld", &(metadata->Throughput)); i++; } else if (jsoneq(json->data, &t[i], "DMA_type") == 0) { if(strcmp(json->data + t[i + 1].start, "HLS_MULTICHANNEL_DMA")) metadata->DMA_type = HLS_MULTICHANNEL_DMA; //printf("%.*s\n", t[i + 1].end - t[i + 1].start, // json->data + t[i + 1].start); i++; } else if (jsoneq(json->data, &t[i], "Accel_Handshake_Type") == 0) { //printf("%.*s\n", t[i + 1].end - t[i + 1].start, // json->data + t[i + 1].start); i++; } } return 0; } int json2device(Json_t* json, Metadata_t *metadata, int index){ jsmn_parser p; jsmntok_t t[128]; /* We expect no more than 128 tokens */ jsmn_init(&p); int r = jsmn_parse(&p, json->data, json->size, t, sizeof(t) / sizeof(t[0])); if (r < 0) { printf("Failed to parse JSON: %d\n", r); return 1; } /* Assume the top-level element is an object */ if (r < 1 || t[0].type != JSMN_OBJECT) { printf("Object expected\n"); return 1; } for (int i = 1; i < r; i++) { if (jsoneq(json->data, &t[i], "dev_name") == 0) { sprintf(metadata->plDevices[index].name, "%.*s", t[i + 1].end - t[i + 1].start, json->data + t[i + 1].start); i++; } else if (jsoneq(json->data, &t[i], "reg_base") == 0) { sscanf(json->data + t[i + 1].start, "0x%lx", &(metadata->plDevices[index].base)); i++; } else if (jsoneq(json->data, &t[i], "reg_size") == 0) { sscanf(json->data + t[i + 1].start, "%ld", &(metadata->plDevices[index].size)); i++; } } return 0; } int json2devices(Json_t* json, Metadata_t *metadata){ jsmn_parser p; jsmntok_t t[128]; /* We expect no more than 128 tokens */ jsmn_init(&p); int r = jsmn_parse(&p, json->data, json->size, t, sizeof(t) / sizeof(t[0])); if (r < 0) { printf("Failed to parse JSON: %d\n", r); return 1; } if (r < 1 || t[0].type != JSMN_ARRAY) { printf("Object expected\n"); return 1; } metadata->plDevices_Count = t[0].size; for (int i = 0, j=0; i < r; i++) { if (t[i].parent != 0) { continue; /* We expect groups to be an array of strings */ } Json_t* subJson = malloc(sizeof(Json_t)); subJson->data = json->data + t[i].start; subJson->size = t[i].end - t[i].start; json2device(subJson, metadata, j); j++; } return 0; } int json2meta(Json_t* json, Metadata_t *metadata){ jsmn_parser p; jsmntok_t t[128]; /* We expect no more than 128 tokens */ jsmn_init(&p); int r = jsmn_parse(&p, json->data, json->size, t, sizeof(t) / sizeof(t[0])); if (r < 0) { printf("Failed to parse JSON: %d\n", r); return 1; } /* Assume the top-level element is an object */ if (r < 1 || t[0].type != JSMN_OBJECT) { printf("Object expected\n"); return 1; } /* Loop over all keys of the root object */ for (int i = 1; i < r; i++) { if (jsoneq(json->data, &t[i], "accel_type") == 0) { sprintf(metadata->accel_type, "%.*s", t[i + 1].end - t[i + 1].start, json->data + t[i + 1].start); i++; } else if (jsoneq(json->data, &t[i], "accel_devices") == 0) { //printf("%.*s\n", t[i + 1].end - t[i + 1].start, // json->data + t[i + 1].start); Json_t* subJson = malloc(sizeof(Json_t)); subJson->data = json->data + t[i + 1].start; subJson->size = t[i + 1].end - t[i + 1].start; json2devices(subJson, metadata); i++; } else if (jsoneq(json->data, &t[i], "accel_metadata") == 0) { //printf("%.*s\n", t[i + 1].end - t[i + 1].start, // json->data + t[i + 1].start); Json_t* subJson = malloc(sizeof(Json_t)); subJson->data = json->data + t[i + 1].start; subJson->size = t[i + 1].end - t[i + 1].start; json2metadata(subJson, metadata); i++; } } return 0; } int str2json(char* str, Json_t *json){ json->size = strlen(str); json->data = str; //malloc(json->size + 1); json->data[json->size] = 0; //INFO("%s\n", json->data); return 0; } int file2json(char* filename, Json_t *json){ FILE *f = fopen(filename, "rb"); fseek(f, 0, SEEK_END); json->size = ftell(f); fseek(f, 0, SEEK_SET); json->data = malloc(json->size + 1); int len = fread(json->data, json->size, 1, f); _unused(len); fclose(f); json->data[json->size] = 0; INFO("%s\n", json->data); return 0; } int printMeta(Metadata_t *metadata){ INFOP("accel_type : %s\n", metadata->accel_type); INFOP("fallback :\n"); INFOP("\tlib : %s\n", metadata->fallback.lib); INFOP("\tbehaviour : %d\n", metadata->fallback.behaviour); INFOP("interRM :\n"); INFOP("\tcompatible : %d\n", metadata->interRM.compatible); INFOP("\taddress : %lx\n", metadata->interRM.address); for(int i = 0; i < metadata->plDevices_Count; i ++){ INFOP("plDevice :\n"); INFOP("\tname : %s\n", metadata->plDevices[i].name); INFOP("\tbase : %lx\n", metadata->plDevices[i].base); INFOP("\tsize : %lx\n", metadata->plDevices[i].size); INFOP("\ttype : %d\n", metadata->plDevices[i].type); } INFOP("Input_Data_Block_Size : %lx\n", metadata->Input_Data_Block_Size); INFOP("Output_Data_Block_Size: %lx\n", metadata->Output_Data_Block_Size); INFOP("Input_Channel_Count : %d\n", metadata->Input_Channel_Count); INFOP("Output_Channel_Count : %d\n", metadata->Output_Channel_Count); INFOP("Config_Buffer_Size : %lx\n", metadata->Config_Buffer_Size); INFOP("Input_Buffer_Size : %lx\n", metadata->Input_Buffer_Size); INFOP("Output_Buffer_Size : %lx\n", metadata->Output_Buffer_Size); INFOP("Throughput : %ld\n", metadata->Throughput); INFOP("DMA_type : %d\n", metadata->DMA_type); INFOP("Accel_Handshake_Type : %d\n", metadata->Accel_Handshake_Type); return 0; } int json2accelNode(Json_t* json, AbstractGraph_t *graph, int index){ _unused(json); _unused(graph); _unused(index); return 0; } int json2accelNodes(Json_t* json, AbstractGraph_t *graph){ jsmn_parser p; jsmntok_t t[128]; jsmn_init(&p); int r = jsmn_parse(&p, json->data, json->size, t, sizeof(t) / sizeof(t[0])); if (r < 0) { printf("Failed to parse JSON: %d\n", r); return 1; } if (r < 1 || t[0].type != JSMN_ARRAY) { printf("Object expected\n"); return 1; } printf("%d\n", t[0].size); for (int i = 0, j=0; i < r; i++) { if (t[i].parent != 0) { continue; } printf("%.*s\n", t[i].end - t[i].start, json->data + t[i].start); Json_t* subJson = malloc(sizeof(Json_t)); subJson->data = json->data + t[i].start; subJson->size = t[i].end - t[i].start; json2accelNode(subJson, graph, j); j++; } return 0; } int json2buffNodes(Json_t* json, AbstractGraph_t *graph){ jsmn_parser p; jsmntok_t t[128]; jsmn_init(&p); _unused(graph); int r = jsmn_parse(&p, json->data, json->size, t, sizeof(t) / sizeof(t[0])); if (r < 0) { printf("Failed to parse JSON: %d\n", r); return 1; } if (r < 1 || t[0].type != JSMN_ARRAY) { printf("Object expected\n"); return 1; } printf("%d\n", t[0].size); for (int i = 0, j=0; i < r; i++) { if (t[i].parent != 0) { continue; } printf("%.*s\n", t[i].end - t[i].start, json->data + t[i].start); Json_t* subJson = malloc(sizeof(Json_t)); subJson->data = json->data + t[i].start; subJson->size = t[i].end - t[i].start; //json2accelNode(subJson, graph, j); j++; } return 0; } int json2links(Json_t* json, AbstractGraph_t *graph){ jsmn_parser p; jsmntok_t t[128]; jsmn_init(&p); _unused(graph); int r = jsmn_parse(&p, json->data, json->size, t, sizeof(t) / sizeof(t[0])); if (r < 0) { printf("Failed to parse JSON: %d\n", r); return 1; } if (r < 1 || t[0].type != JSMN_ARRAY) { printf("Object expected\n"); return 1; } printf("%d\n", t[0].size); for (int i = 0, j=0; i < r; i++) { if (t[i].parent != 0) { continue; } printf("%.*s\n", t[i].end - t[i].start, json->data + t[i].start); Json_t* subJson = malloc(sizeof(Json_t)); subJson->data = json->data + t[i].start; subJson->size = t[i].end - t[i].start; //json2accelNode(subJson, graph, j); j++; } return 0; } int graphParser(char* jsonStr, AbstractGraph_t **graph){ AbstractGraph_t *tgraph = *graph; Json_t* json = malloc(sizeof(Json_t)); jsmn_parser p; jsmntok_t t[1024]; /* We expect no more than 128 tokens */ jsmn_init(&p); json->size = strlen(jsonStr); json->data = malloc(json->size + 1); strcpy(json->data, jsonStr); int r = jsmn_parse(&p, json->data, json->size, t, sizeof(t) / sizeof(t[0])); if (r < 0) { INFO("Failed to parse JSON: %d\n", r); return 1; } /* Assume the top-level element is an object */ if (r < 1 || t[0].type != JSMN_OBJECT) { INFO("Object expected\n"); return 1; } for (int i = 1; i < r; i++) { if (t[i].parent != 0) { continue; } if (jsoneq(json->data, &t[i], "id") == 0) { sscanf(json->data + t[i + 1].start, "%d", &(tgraph->id)); //INFO("id: %d\n", tgraph->id); i++; } else if (jsoneq(json->data, &t[i], "type") == 0) { sscanf(json->data + t[i + 1].start, "%hhd", &(tgraph->type)); //INFO("type: %d\n", tgraph->type); i++; } else if (jsoneq(json->data, &t[i], "accelNode") == 0) { i ++; int arrayElementCount = t[i].size; int array = i; int objectElementCount = 0; int object = 0; i ++; for (int j = 0; j < arrayElementCount; j++) { if (t[i + j].parent == array) { objectElementCount = t[i + j].size; object = i + j; i ++; AbstractAccelNode_t *accelNode = malloc(sizeof(AbstractAccelNode_t)); Element_t* element = (Element_t *) malloc(sizeof(Element_t)); element->node = accelNode; tgraph->accelNodeID ++; element->head = NULL; element->tail = NULL; addElement(&(tgraph->accelNodeHead), element); for (int k = 0; k < objectElementCount; k++) { if (t[i + j + k].parent == object) { if (jsoneq(json->data, &t[i + j + k], "id") == 0) { sscanf(json->data + t[i + j + k + 1].start, "%d", &(accelNode->id)); } else if (jsoneq(json->data, &t[i + j + k], "type") == 0) { sscanf(json->data + t[i + j + k + 1].start, "%hhd", &(accelNode->type)); if(accelNode->type == HW_NODE){ tgraph->accelCount ++; } } else if (jsoneq(json->data, &t[i + j + k], "name") == 0) { memset(accelNode->name, '\0', 256); sprintf(accelNode->name, "%.*s", t[i + j + k + 1].end - t[i + j + k + 1].start, json->data + t[i + j + k + 1].start); } else if (jsoneq(json->data, &t[i + j + k], "size") == 0) { sscanf(json->data + t[i + j + k + 1].start, "%d", &(accelNode->size)); } else if (jsoneq(json->data, &t[i + j + k], "semaphore") == 0) { sscanf(json->data + t[i + j + k + 1].start, "%d", &(accelNode->semaphore)); } } else{ i ++; k --; continue; } } } else{ i ++; j --; continue; } } i++; } else if (jsoneq(json->data, &t[i], "buffNode") == 0) { i ++; int arrayElementCount = t[i].size; int array = i; int objectElementCount = 0; int object = 0; i ++; for (int j = 0; j < arrayElementCount; j++) { if (t[i + j].parent == array) { objectElementCount = t[i + j].size; object = i + j; i ++; AbstractBuffNode_t *buffNode = malloc(sizeof(AbstractBuffNode_t)); Element_t* element = (Element_t *) malloc(sizeof(Element_t)); element->node = buffNode; tgraph->buffNodeID ++; element->head = NULL; element->tail = NULL; addElement(&(tgraph->buffNodeHead), element); for (int k = 0; k < objectElementCount; k++) { if (t[i + j + k].parent == object) { if (jsoneq(json->data, &t[i + j + k], "id") == 0) { sscanf(json->data + t[i + j + k + 1].start, "%d", &(buffNode->id)); } else if (jsoneq(json->data, &t[i + j + k], "type") == 0) { sscanf(json->data + t[i + j + k + 1].start, "%hhd", &(buffNode->type)); } else if (jsoneq(json->data, &t[i + j + k], "name") == 0) { memset(buffNode->name, '\0', 256); sprintf(buffNode->name, "%.*s", t[i + j + k + 1].end - t[i + j + k + 1].start, json->data + t[i + j + k + 1].start); } else if (jsoneq(json->data, &t[i + j + k], "size") == 0) { sscanf(json->data + t[i + j + k + 1].start, "%d", &(buffNode->size)); } } else{ i ++; k --; continue; } } } else{ i ++; j --; continue; } } i++; } else if (jsoneq(json->data, &t[i], "links") == 0) { i ++; int arrayElementCount = t[i].size; int array = i; int objectElementCount = 0; int object = 0; i ++; //printf("#%d %d\n", arrayElementCount, array); for (int j = 0; j < arrayElementCount; j++) { if (t[i + j].parent == array) { objectElementCount = t[i + j].size; object = i + j; //printf("%d %d\n", objectElementCount, object); i ++; AbstractLink_t *link = malloc(sizeof(AbstractLink_t)); Element_t* element = (Element_t *) malloc(sizeof(Element_t)); element->node = link; tgraph->linkID ++; element->head = NULL; element->tail = NULL; addElement(&(tgraph->linkHead), element); for (int k = 0; k < objectElementCount; k++) { if (t[i + j + k].parent == object) { if (jsoneq(json->data, &t[i + j + k], "id") == 0) { sscanf(json->data + t[i + j + k + 1].start, "%d", &(link->id)); } else if (jsoneq(json->data, &t[i + j + k], "accelNode") == 0) { uint32_t nodeid; Element_t *accelElement = tgraph->accelNodeHead; sscanf(json->data + t[i + j + k + 1].start, "%d", &(nodeid)); //link->accelNode)); //printf("nodeid : %d\n", nodeid); //INFO(" %d\n", nodeid); while(accelElement != NULL){ //INFO("# %d\n", ((AbstractAccelNode_t*)accelElement->node)->id); if (((AbstractAccelNode_t*)accelElement->node)->id == nodeid){ link->accelNode = (AbstractAccelNode_t*)accelElement->node; //INFO("### %s\n", link->accelNode->name); break; } accelElement = accelElement->tail; } } else if (jsoneq(json->data, &t[i + j + k], "buffNode") == 0) { uint32_t nodeid; Element_t *buffElement = tgraph->buffNodeHead; sscanf(json->data + t[i + j + k + 1].start, "%d", &(nodeid)); //link->accelNode)); //printf("nodeid : %d\n", nodeid); while(buffElement != NULL){ if (((AbstractBuffNode_t*)buffElement->node)->id == nodeid){ link->buffNode = (AbstractBuffNode_t*)buffElement->node; break; } buffElement = buffElement->tail; } } else if (jsoneq(json->data, &t[i + j + k], "type") == 0) { sscanf(json->data + t[i + j + k + 1].start, "%hhd", &(link->type)); } else if (jsoneq(json->data, &t[i + j + k], "transactionIndex") == 0) { sscanf(json->data + t[i + j + k + 1].start, "%hhd", &(link->transactionIndex)); } else if (jsoneq(json->data, &t[i + j + k], "transactionSize") == 0) { sscanf(json->data + t[i + j + k + 1].start, "%d", &(link->transactionSize)); } else if (jsoneq(json->data, &t[i + j + k], "offset") == 0) { sscanf(json->data + t[i + j + k + 1].start, "%d", &(link->offset)); } else if (jsoneq(json->data, &t[i + j + k], "channel") == 0) { sscanf(json->data + t[i + j + k + 1].start, "%hhd", &(link->channel)); } } else{ i ++; k --; continue; } } } else{ i ++; j --; continue; } } i++; } } return 0; } int graphIDParser(char* jsonStr){ int id; Json_t* json = malloc(sizeof(Json_t)); jsmn_parser p; jsmntok_t t[1024]; /* We expect no more than 128 tokens */ jsmn_init(&p); json->size = strlen(jsonStr); json->data = malloc(json->size + 1); strcpy(json->data, jsonStr); int r = jsmn_parse(&p, json->data, json->size, t, sizeof(t) / sizeof(t[0])); if (r < 0) { INFO("Failed to parse JSON: %d\n", r); return 1; } /* Assume the top-level element is an object */ if (r < 1 || t[0].type != JSMN_OBJECT) { INFO("Object expected\n"); return 1; } for (int i = 1; i < r; i++) { if (t[i].parent != 0) { continue; } if (jsoneq(json->data, &t[i], "id") == 0) { sscanf(json->data + t[i + 1].start, "%d", &(id)); break; } } return id; } dfx-mgr-xilinx_v2023.2/src/sys/linux/graph/metadata.h000066400000000000000000000026731446677152000225510ustar00rootroot00000000000000/* * Copyright (c) 2021, Xilinx Inc. and Contributors. All rights reserved. * * SPDX-License-Identifier: MIT */ #include typedef struct Fallback Fallback_t; typedef struct InterRM InterRM_t; typedef struct PLDevice PLDevice_t; typedef struct Metadata Metadata_t; typedef struct Json Json_t; struct PLDevice{ char name[100]; uint64_t base; uint64_t size; uint8_t type; }; //#define NONE 0x00 #define LIB 0x01 #define USER_DEFINED 0x02 struct Fallback{ char lib[100]; int behaviour; }; struct InterRM{ int compatible; uint64_t address; }; struct Metadata{ struct Fallback fallback; struct InterRM interRM; struct PLDevice plDevices[10]; char lib[100]; char accel_type[100]; uint8_t plDevices_Count; uint64_t Input_Data_Block_Size; uint64_t Output_Data_Block_Size; uint8_t Input_Channel_Count; uint8_t Output_Channel_Count; uint64_t Config_Buffer_Size; uint64_t Input_Buffer_Size; uint64_t Output_Buffer_Size; uint64_t Throughput; uint8_t DMA_type; uint8_t Accel_Handshake_Type; }; struct Json{ int size; char* data; }; extern int json2meta(Json_t* json, Metadata_t *metadata); extern int printMeta(Metadata_t *metadata); extern int file2json(char* filename, Json_t *json); extern int str2json(char* str, Json_t *json); typedef struct AbstractGraph AbstractGraph_t; typedef struct Element Element_t; extern int graphParser(char* jsonStr, AbstractGraph_t **graph); extern int graphIDParser(char* jsonStr); dfx-mgr-xilinx_v2023.2/src/sys/linux/graph/scheduler.c000066400000000000000000000271661446677152000227460ustar00rootroot00000000000000/* * Copyright (c) 2021, Xilinx Inc. and Contributors. All rights reserved. * * SPDX-License-Identifier: MIT */ #include #include #include #include #include "layer0/utils.h" #include "layer0/queue.h" #include "graph.h" #include "scheduler.h" #include #include #include int printTransaction(Schedule_t *schedule, char* message){ if(schedule){ int dependent = schedule->dependency->linkCount; AccelNode_t *accelNode = schedule->dependency->link->accelNode; BuffNode_t *buffNode = schedule->dependency->link->buffNode; int interRMCompatible = buffNode->buffer.InterRMCompatible; BuffNode_t *dbuffNode = NULL; if(dependent){ dbuffNode = schedule->dependency->dependentLinks[ schedule->dependency->linkCount - 1]->buffNode; } INFOP("%d : %x: ", schedule->index, schedule->dependency->link->transactionIndex); INFOP("(%x) %s%d irm%d (%x, %x) ", schedule->status, accelNode->accel.name, accelNode->accel.index, accelNode->accel.InterRMCompatible, accelNode->S2MMStatus, accelNode->MM2SStatus); if(schedule->dependency->link->type){ INFOP("====> "); }else{ INFOP("<==== "); } INFOP("%s%d irm%d typ%d (%x %d)", buffNode->buffer.name, buffNode->buffer.index, buffNode->buffer.InterRMCompatible, buffNode->buffer.type, buffNode->status, schedule->dependency->link->channel); if(dependent){ INFOP("depends on %s%d (%x) (%x)", dbuffNode->buffer.name, dbuffNode->buffer.index, dbuffNode->status, interRMCompatible); } INFOP(" %s\n", message); } return 0; } void *scheduler_Task(void* carg){ //INFO("\n"); AcapGraph_t *acapGraph = carg; Scheduler_t *scheduler = acapGraph->scheduler; queue_t *commandQueue = scheduler->CommandQueue; queue_t *responseQueue = scheduler->ResponseQueue; ScQueueBuffer_t *commandQueueBuffer, *responseQueueBuffer; int busy = 0; int enableScheduler = 0; while(1){ usleep(1000); if((busy == 0) && (queue_size(commandQueue) > 0)){ commandQueueBuffer = queue_dequeue(commandQueue); switch (commandQueueBuffer->type){ case SCHEDULER_COMPLETION: INFOP("processing SCHEDULER_COMPLETION\n"); responseQueueBuffer = malloc(sizeof(ScQueueBuffer_t)); responseQueueBuffer->type = SCHEDULER_COMPLETION; queue_enqueue(responseQueue, responseQueueBuffer); break; case SCHEDULER_TASKEND: INFOP("processing TASKEND\n"); return NULL; break; case SCHEDULER_STATUS: INFOP("Status Requested\n"); responseQueueBuffer = malloc(sizeof(ScQueueBuffer_t)); responseQueueBuffer->type = SCHEDULER_STATUS; responseQueueBuffer->busy = busy; queue_enqueue(responseQueue, responseQueueBuffer); break; case SCHEDULER_TRIGGER: INFOP("processing TRIGGER\n"); busy = 1; enableScheduler = 1; //getRMInfo(); break; default: break; } } if(enableScheduler){ Schedule_t *schedule = acapGraph->scheduleHead; if(schedule != NULL){ while(1){ usleep(100); //printf("######\n"); if(schedule == NULL){ break; } int dependent = schedule->dependency->linkCount; int readerCount = schedule->dependency->link->buffNode->buffer.readerCount; AccelNode_t *accelNode = schedule->dependency->link->accelNode; BuffNode_t *buffNode = schedule->dependency->link->buffNode; BuffNode_t *dbuffNode = NULL; int interRMCompatible = buffNode->buffer.InterRMCompatible; int transactionIndex = schedule->dependency->link->transactionIndex; if(dependent){ dbuffNode = schedule->dependency->dependentLinks[ schedule->dependency->linkCount - 1]->buffNode; _unused(dbuffNode); } //printTransaction(schedule, "scheduler"); if(accelNode->currentTransactionIndex == 0) { accelNode->currentTransactionIndex = transactionIndex; //printf("######2\n"); } //###################################################### if(schedule->dependency->link->type){ //printf("######3\n"); if(schedule->status == 0 && buffNode->status == 0 && (((accelNode->accel.type == IO_NODE || accelNode->accel.type == HW_NODE) && accelNode->MM2SStatus == 0) || (accelNode->accel.type == IN_NODE)) && accelNode->S2MMStatus == 0 && accelNode->currentTransactionIndex == transactionIndex ){ //printf("%p\n", buffNode->buffer->ptr); accelNode->S2MMStatus = 1; buffNode->status = 1; schedule->status = 1; printTransaction(schedule, "S2MM Transaction Scheduled"); break; } else if(schedule->status == 1 && buffNode->status == 1 && (((accelNode->accel.type == IO_NODE || accelNode->accel.type == HW_NODE) && accelNode->MM2SStatus == 1) || (accelNode->accel.type == IN_NODE)) && accelNode->S2MMStatus == 1){ accelNode->S2MMStatus = 2; buffNode->status = 2; //printf("######5\n"); //printf("%p\n", buffNode->buffer.ptr); accelNode->accel.datamover->S2MMData( accelNode->accel.datamover->dmstruct, &buffNode->buffer, schedule->offset, schedule->size, schedule->first ); printTransaction(schedule, "S2MM Transaction Triggered"); } else if(schedule->status == 1 && buffNode->status == 2 && (((accelNode->accel.type == IO_NODE || accelNode->accel.type == HW_NODE) && accelNode->MM2SStatus == 2) || (accelNode->accel.type == IN_NODE)) && accelNode->S2MMStatus == 2){ int status = accelNode->accel.datamover->S2MMDone( accelNode->accel.datamover->dmstruct, &buffNode->buffer); if(status == 1){ buffNode->status = 3; accelNode->S2MMStatus = 0; accelNode->currentTransactionIndex = 0; printTransaction(schedule, "S2MM Transaction Done"); delSchedule(&schedule, &(acapGraph->scheduleHead)); continue; } else{ printTransaction(schedule, "S2MM scheduler #"); printf("S2MM status : %d\n", status); } } }else{ //printf("######4\n"); if(accelNode->currentTransactionIndex == 0) { accelNode->currentTransactionIndex = transactionIndex; } //printf("###1\n"); if(schedule->status == 0 && (buffNode->status == 3 || ( //buffNode->buffer.type == 1 && interRMCompatible == 2 && buffNode->status == 2)) && (((accelNode->accel.type == IO_NODE || accelNode->accel.type == HW_NODE) && ((dependent && accelNode->S2MMStatus == 1) || !dependent)) || (accelNode->accel.type == OUT_NODE)) && accelNode->MM2SStatus == 0 && accelNode->currentTransactionIndex == transactionIndex){ accelNode->MM2SStatus = 1; schedule->status = 1; printTransaction(schedule, "MM2S Transaction Scheduled"); break; } else if(schedule->status == 1 && (buffNode->status == 3 || ( //buffNode->buffer.type == 1 && interRMCompatible == 2 && buffNode->status == 2)) && (((accelNode->accel.type == IO_NODE || accelNode->accel.type == HW_NODE) && ((dependent && accelNode->S2MMStatus == 2) || !dependent)) || (accelNode->accel.type == OUT_NODE)) && accelNode->MM2SStatus == 1){ accelNode->MM2SStatus = 2; accelNode->accel.datamover->MM2SData( accelNode->accel.datamover->dmstruct, &buffNode->buffer, schedule->offset, schedule->size, schedule->last, schedule->dependency->link->channel ); printTransaction(schedule, "MM2S Transaction Triggered"); } else if(schedule->status == 1 && (buffNode->status == 3) && (((accelNode->accel.type == IO_NODE || accelNode->accel.type == HW_NODE) && ((dependent && accelNode->S2MMStatus == 0) || !dependent)) || (accelNode->accel.type == OUT_NODE)) && accelNode->MM2SStatus == 2){ int status = accelNode->accel.datamover->MM2SDone( accelNode->accel.datamover->dmstruct, &buffNode->buffer); if(status == 1){ buffNode->readStatus += 1; char msg[100]; sprintf(msg, "MM2S Transaction Done %d %d", buffNode->readStatus, readerCount); if(buffNode->readStatus == readerCount){ buffNode->status = 0; buffNode->readStatus = 0; } accelNode->MM2SStatus = 0; accelNode->currentTransactionIndex = 0; printTransaction(schedule, msg); delSchedule(&schedule, &(acapGraph->scheduleHead)); continue; } else{ printTransaction(schedule, "MM2S scheduler #"); printf("MM2S status : %d\n", status); } } } //printf("######################################################\n"); if(schedule->tail != NULL){ schedule = schedule->tail; } else break; } }else{ busy = 0; printf("Scheduler Done !!\n"); } } } return NULL; } int SchedulerInit(AcapGraph_t *acapGraph){ //INFO("\n"); Scheduler_t *scheduler = malloc(sizeof(Scheduler_t)); acapGraph->scheduler = scheduler; scheduler->CommandQueue = malloc(sizeof(queue_t)); scheduler->ResponseQueue = malloc(sizeof(queue_t)); *(scheduler->CommandQueue ) = (queue_t) { malloc(sizeof(void*)*1000), 1000, 0, 0, 0, PTHREAD_MUTEX_INITIALIZER, PTHREAD_COND_INITIALIZER, PTHREAD_COND_INITIALIZER }; *(scheduler->ResponseQueue) = (queue_t) { malloc(sizeof(void*)*1000), 1000, 0, 0, 0, PTHREAD_MUTEX_INITIALIZER, PTHREAD_COND_INITIALIZER, PTHREAD_COND_INITIALIZER }; pthread_create(scheduler->thread , NULL, scheduler_Task, acapGraph); return 0; } int TaskEnd(Scheduler_t *scheduler){ //INFO("\n"); ScQueueBuffer_t *CommandBuff; CommandBuff = malloc(sizeof(ScQueueBuffer_t)); CommandBuff->type = SCHEDULER_TASKEND; queue_enqueue(scheduler->CommandQueue, CommandBuff); return 0; } int SchedulerFinalise(AcapGraph_t *acapGraph){ //INFO("\n"); Scheduler_t *scheduler = acapGraph->scheduler; TaskEnd(scheduler); pthread_join(scheduler->thread[0], NULL); return 0; } int SchedulerTrigger(AcapGraph_t *acapGraph){ //INFO("%s%d\n", buffer->name, buffer->index); ScQueueBuffer_t *CommandBuff; CommandBuff = malloc(sizeof(ScQueueBuffer_t)); CommandBuff->type = SCHEDULER_TRIGGER; queue_enqueue(acapGraph->scheduler->CommandQueue, CommandBuff); return 0; } int SchedulerCompletion(AcapGraph_t *acapGraph){ //INFO("\n"); ScQueueBuffer_t *responseQueueBuffer, *commandBuff; commandBuff = malloc(sizeof(ScQueueBuffer_t)); commandBuff->type = SCHEDULER_COMPLETION; queue_enqueue(acapGraph->scheduler->CommandQueue, commandBuff); while(1){ //INFO("%d\n",queue_size(datamover->S2MMResponseQueue)) //if(queue_size(datamover->S2MMResponseQueue) > 0){ responseQueueBuffer = queue_dequeue(acapGraph->scheduler->ResponseQueue); if(responseQueueBuffer->type == SCHEDULER_COMPLETION) break; //} } //getRMInfo(); return 0; } int SchedulerStatus(AcapGraph_t *acapGraph){ //INFO("\n"); ScQueueBuffer_t *responseQueueBuffer, *commandBuff; commandBuff = malloc(sizeof(ScQueueBuffer_t)); commandBuff->type = SCHEDULER_STATUS; queue_enqueue(acapGraph->scheduler->CommandQueue, commandBuff); while(1){ //INFO("%d\n",queue_size(datamover->S2MMResponseQueue)) //if(queue_size(datamover->S2MMResponseQueue) > 0){ responseQueueBuffer = queue_dequeue(acapGraph->scheduler->ResponseQueue); if(responseQueueBuffer->type == SCHEDULER_STATUS) return responseQueueBuffer->busy; //} } return 0; } dfx-mgr-xilinx_v2023.2/src/sys/linux/graph/scheduler.h000066400000000000000000000012271446677152000227410ustar00rootroot00000000000000/* * Copyright (c) 2021, Xilinx Inc. and Contributors. All rights reserved. * * SPDX-License-Identifier: MIT */ //#include "dm.h" #define SCHEDULER_TASKEND 0x00FF #define SCHEDULER_STATUS 0x00F0 #define SCHEDULER_TRIGGER 0x00F1 #define SCHEDULER_COMPLETION 0x00F2 typedef struct ScQueueBuffer{ int type; char filename[1024]; DFXBuffer_t* buffer; DFXBuffer_t* dependentBuffer; int busy; double throughput; }ScQueueBuffer_t; extern int SchedulerInit(AcapGraph_t *acapGraph); extern int SchedulerFinalise(AcapGraph_t *acapGraph); extern int SchedulerCompletion(AcapGraph_t *acapGraph); extern int SchedulerTrigger(AcapGraph_t *acapGraph); dfx-mgr-xilinx_v2023.2/src/sys/linux/graph/schedulerBypass.c000066400000000000000000000233231446677152000241170ustar00rootroot00000000000000/* * Copyright (c) 2021, Xilinx Inc. and Contributors. All rights reserved. * * SPDX-License-Identifier: MIT */ #include #include #include #include #include "layer0/utils.h" #include "graph.h" #include "scheduler.h" #include #include int printTransaction(Schedule_t *schedule){ if(schedule){ int dependent = schedule->dependency->linkCount; AccelNode_t *accelNode = schedule->dependency->link->accelNode; BuffNode_t *buffNode = schedule->dependency->link->buffNode; int interRMCompatible = buffNode->buffer.InterRMCompatible; BuffNode_t *dbuffNode = NULL; if(dependent){ dbuffNode = schedule->dependency->dependentLinks[ schedule->dependency->linkCount - 1]->buffNode; } INFOP("(%x) %s%d (%x, %x) ", schedule->status, accelNode->accel.name, accelNode->accel.index, accelNode->S2MMStatus, accelNode->MM2SStatus); if(schedule->dependency->link->type){ INFOP("====> "); }else{ INFOP("<==== "); } INFOP("%s%d (%x %d)", buffNode->buffer.name, buffNode->buffer.index, buffNode->status, schedule->dependency->link->channel); if(dependent){ INFOP("depends on %s%d (%x) (%x)", dbuffNode->buffer.name, dbuffNode->buffer.index, dbuffNode->status, interRMCompatible); } INFOP("\n"); } return 0; } void *bypass_Task(void* carg){ INFO("\n"); AcapGraph_t *acapGraph = carg; Scheduler_t *scheduler = acapGraph->scheduler; queue_t *commandQueue = scheduler->CommandQueue; queue_t *responseQueue = scheduler->ResponseQueue; ScQueueBuffer_t *commandQueueBuffer, *responseQueueBuffer; int busy = 0; int enableScheduler = 0; while(1){ usleep(1000); if((busy == 0) && (queue_size(commandQueue) > 0)){ commandQueueBuffer = queue_dequeue(commandQueue); switch (commandQueueBuffer->type){ case SCHEDULER_COMPLETION: INFO("processing SCHEDULER_COMPLETION\n"); responseQueueBuffer = malloc(sizeof(ScQueueBuffer_t)); responseQueueBuffer->type = SCHEDULER_COMPLETION; queue_enqueue(responseQueue, responseQueueBuffer); break; case SCHEDULER_TASKEND: INFO("processing TASKEND\n"); return NULL; break; case SCHEDULER_TRIGGER: INFO("processing TRIGGER\n"); busy = 1; enableScheduler = 1; break; default: break; } } if(enableScheduler){ Schedule_t *schedule = acapGraph->scheduleHead; if(schedule != NULL){ while(1){ usleep(100); if(schedule == NULL){ break; } int dependent = schedule->dependency->linkCount; int readerCount = schedule->dependency->link->buffNode->buffer.readerCount; AccelNode_t *accelNode = schedule->dependency->link->accelNode; BuffNode_t *buffNode = schedule->dependency->link->buffNode; BuffNode_t *dbuffNode = NULL; int interRMCompatible = buffNode->buffer.InterRMCompatible; int transactionIndex = schedule->dependency->link->transactionIndex; if(dependent){ dbuffNode = schedule->dependency->dependentLinks[ schedule->dependency->linkCount - 1]->buffNode; _unused(dbuffNode); } if(accelNode->currentTransactionIndex == 0) { accelNode->currentTransactionIndex = transactionIndex; } //###################################################### if(schedule->dependency->link->type){ if(schedule->status == 0 && buffNode->status == 0 && (((accelNode->accel.type == IO_NODE || accelNode->accel.type == HW_NODE) && accelNode->MM2SStatus == 0) || (accelNode->accel.type == IN_NODE)) && accelNode->S2MMStatus == 0 && accelNode->currentTransactionIndex == transactionIndex ){ accelNode->S2MMStatus = 1; buffNode->status = 1; schedule->status = 1; printTransaction(schedule); INFO("Transaction Scheduled \n"); break; } else if(schedule->status == 1 && buffNode->status == 1 && (((accelNode->accel.type == IO_NODE || accelNode->accel.type == HW_NODE) && accelNode->MM2SStatus == 1) || (accelNode->accel.type == IN_NODE)) && accelNode->S2MMStatus == 1){ accelNode->S2MMStatus = 2; buffNode->status = 2; accelNode->accel.datamover->S2MMData( accelNode->accel.datamover->dmstruct, &buffNode->buffer, schedule->offset, schedule->size ); printTransaction(schedule); INFO("Transaction Triggered #\n"); } else if(schedule->status == 1 && buffNode->status == 2 && (((accelNode->accel.type == IO_NODE || accelNode->accel.type == HW_NODE) && accelNode->MM2SStatus == 2) || (accelNode->accel.type == IN_NODE)) && accelNode->S2MMStatus == 2){ int status = accelNode->accel.datamover->S2MMDone( accelNode->accel.datamover->dmstruct, &buffNode->buffer); if(status == 1){ buffNode->status = 3; accelNode->S2MMStatus = 0; accelNode->currentTransactionIndex = 0; printTransaction(schedule); INFO("Transaction Done \n"); delSchedule(&schedule, &(acapGraph->scheduleHead)); continue; } } }else{ if(accelNode->currentTransactionIndex == 0) { accelNode->currentTransactionIndex = transactionIndex; } if(schedule->status == 0 && (buffNode->status == 3 || (interRMCompatible == 2 && buffNode->status == 2)) && (((accelNode->accel.type == IO_NODE || accelNode->accel.type == HW_NODE) && ((dependent && accelNode->S2MMStatus == 1) || !dependent)) || (accelNode->accel.type == OUT_NODE)) && accelNode->MM2SStatus == 0 && accelNode->currentTransactionIndex == transactionIndex ){ accelNode->MM2SStatus = 1; schedule->status = 1; printTransaction(schedule); INFO("Transaction Scheduled \n"); break; } else if(schedule->status == 1 && (buffNode->status == 3 || (interRMCompatible == 2 && buffNode->status == 2)) && (((accelNode->accel.type == IO_NODE || accelNode->accel.type == HW_NODE) && ((dependent && accelNode->S2MMStatus == 2) || !dependent)) || (accelNode->accel.type == OUT_NODE)) && accelNode->MM2SStatus == 1){ accelNode->MM2SStatus = 2; accelNode->accel.datamover->MM2SData( accelNode->accel.datamover->dmstruct, &buffNode->buffer, schedule->offset, schedule->size, schedule->dependency->link->channel ); printTransaction(schedule); INFO("Transaction Triggered #\n"); } else if(schedule->status == 1 && (buffNode->status == 3) && (((accelNode->accel.type == IO_NODE || accelNode->accel.type == HW_NODE) && ((dependent && accelNode->S2MMStatus == 0) || !dependent)) || (accelNode->accel.type == OUT_NODE)) && accelNode->MM2SStatus == 2){ int status = accelNode->accel.datamover->MM2SDone( accelNode->accel.datamover->dmstruct, &buffNode->buffer); if(status == 1){ buffNode->readStatus += 1; if(buffNode->readStatus == readerCount){ buffNode->status = 0; buffNode->readStatus = 0; } accelNode->MM2SStatus = 0; accelNode->currentTransactionIndex = 0; printTransaction(schedule); INFO("Transaction Done \n"); delSchedule(&schedule, &(acapGraph->scheduleHead)); continue; } } } //###################################################### if(schedule->tail != NULL){ schedule = schedule->tail; } else break; } }else{ busy = 0; INFO("Scheduler Done !!\n"); } } } return NULL; } int SchedulerInit(AcapGraph_t *acapGraph){ INFO("\n"); Scheduler_t *scheduler = malloc(sizeof(Scheduler_t)); acapGraph->scheduler = scheduler; scheduler->CommandQueue = malloc(sizeof(queue_t)); scheduler->ResponseQueue = malloc(sizeof(queue_t)); *(scheduler->CommandQueue ) = (queue_t) { malloc(sizeof(void*)*1000), 1000, 0, 0, 0, PTHREAD_MUTEX_INITIALIZER, PTHREAD_COND_INITIALIZER, PTHREAD_COND_INITIALIZER }; *(scheduler->ResponseQueue) = (queue_t) { malloc(sizeof(void*)*1000), 1000, 0, 0, 0, PTHREAD_MUTEX_INITIALIZER, PTHREAD_COND_INITIALIZER, PTHREAD_COND_INITIALIZER }; pthread_create(scheduler->thread , NULL, bypass_Task, acapGraph); return 0; } int TaskEnd(Scheduler_t *scheduler){ INFO("\n"); ScQueueBuffer_t *CommandBuff; CommandBuff = malloc(sizeof(ScQueueBuffer_t)); CommandBuff->type = SCHEDULER_TASKEND; queue_enqueue(scheduler->CommandQueue, CommandBuff); return 0; } int SchedulerFinalise(AcapGraph_t *acapGraph){ INFO("\n"); Scheduler_t *scheduler = acapGraph->scheduler; TaskEnd(scheduler); pthread_join(scheduler->thread[0], NULL); return 0; } int SchedulerTrigger(AcapGraph_t *acapGraph){ //INFO("%s%d\n", buffer->name, buffer->index); ScQueueBuffer_t *CommandBuff; CommandBuff = malloc(sizeof(ScQueueBuffer_t)); CommandBuff->type = SCHEDULER_TRIGGER; queue_enqueue(acapGraph->scheduler->CommandQueue, CommandBuff); return 0; } int SchedulerCompletion(AcapGraph_t *acapGraph){ //INFO("\n"); ScQueueBuffer_t *responseQueueBuffer, *commandBuff; commandBuff = malloc(sizeof(ScQueueBuffer_t)); commandBuff->type = SCHEDULER_COMPLETION; queue_enqueue(acapGraph->scheduler->CommandQueue, commandBuff); while(1){ //INFO("%d\n",queue_size(datamover->S2MMResponseQueue)) //if(queue_size(datamover->S2MMResponseQueue) > 0){ responseQueueBuffer = queue_dequeue(acapGraph->scheduler->ResponseQueue); if(responseQueueBuffer->type == SCHEDULER_COMPLETION) break; //} } return 0; } dfx-mgr-xilinx_v2023.2/src/sys/linux/graph/schedulerBypass.h000066400000000000000000000012311446677152000241160ustar00rootroot00000000000000/* * Copyright (c) 2021, Xilinx Inc. and Contributors. All rights reserved. * * SPDX-License-Identifier: MIT */ //#include "dm.h" #define SCHEDULER_TASKEND 0x00FF #define SCHEDULER_STATUS 0x00F0 #define SCHEDULER_TRIGGER 0x00F1 #define SCHEDULER_COMPLETION 0x00F2 typedef struct ScQueueBuffer{ int type; char filename[1024]; Buffer_t* buffer; Buffer_t* dependentBuffer; int transferSize; double throughput; }ScQueueBuffer_t; extern int SchedulerInit(AcapGraph_t *acapGraph); extern int SchedulerFinalise(AcapGraph_t *acapGraph); extern int SchedulerCompletion(AcapGraph_t *acapGraph); extern int SchedulerTrigger(AcapGraph_t *acapGraph); dfx-mgr-xilinx_v2023.2/src/sys/linux/json-config.c000066400000000000000000000415751446677152000221030ustar00rootroot00000000000000/* * Copyright (c) 2021, Xilinx Inc. and Contributors. All rights reserved. * * SPDX-License-Identifier: MIT */ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #define JSMN_PARENT_LINKS #include static int jsoneq(const char *json, jsmntok_t *tok, const char *s) { if (tok->type == JSMN_STRING && (int)strlen(s) == tok->end - tok->start && strncmp(json + tok->start, s, tok->end - tok->start) == 0) { return 0; } return -1; } /** * rp_comms_inter - parse array of Inter-RP buffer addresses * @base: pointer to the base shell to set inter_rp_comm[] * @jdatat: pointer to the start of json data * @token: pointer to rp_comms_interconnect token * * Parsing array: * "rp_comms_interconnect": [ * "slot0" : "0x080000000.inter_rp_comm", * "slot1" : "0x280000000.inter_rp_comm" * ] */ static void rp_comms_inter(struct basePLDesign *base, char *jdat, jsmntok_t *token) { char slotX[] = "slotX"; uint64_t addr; int i, j; if (token[0].type != JSMN_ARRAY) { DFX_ERR("rp_comms_interconnect needs array"); return; } /* * array of key-value pairs: "slotX" : "0x280000000.inter_rp_comm" * token[i + 1] ----^^^^^ ^---- token[i + 2] * strtoul() gets the addr and ignores ".inter_rp_comm" */ for (i = j = 0; j < token[0].size; j++, i+=2) { slotX[4] = '0' + j; if (!jsoneq(jdat, &token[i + 1], slotX)) { addr = strtoul(jdat + token[i + 2].start, NULL, 16); base->inter_rp_comm[j] = addr; DFX_PR("%d.inter_rp_comm= %#lx", j, addr); } } } int parseAccelJson(acapd_accel_t *accel, char *filename) { struct stat s; long numBytes; jsmn_parser parser; jsmntok_t token[128]; int ret,i; char *jsonData; char *dma_ops; uint32_t buff_size = 0; acapd_device_t *dma_dev; FILE *fptr; fptr = fopen(filename, "r"); if (fptr == NULL){ acapd_print("%s: Cannot open %s\n",__func__,filename); return -1; } if (stat(filename,&s) != 0 || !S_ISREG(s.st_mode)){ acapd_perror("could not open %s\n",filename); return -1; } numBytes = s.st_size; dma_dev = (acapd_device_t *)calloc(1, sizeof(*dma_dev)); if (dma_dev == NULL) { acapd_perror("%s: failed to alloc mem for dma dev.\n", __func__); return -EINVAL; } dma_ops = (char *)calloc(64, sizeof(char)); jsonData = (char *)calloc(numBytes, sizeof(char)); if (jsonData == NULL) return -1; ret = fread(jsonData, sizeof(char), numBytes, fptr); if (ret < numBytes) acapd_perror("%s: Error reading Accel.json\n",__func__); fclose(fptr); jsmn_init(&parser); ret = jsmn_parse(&parser, jsonData, numBytes, token, sizeof(token)/sizeof(token[0])); if (ret < 0){ acapd_praw("Failed to parse JSON: %d\n", ret); } for(i=1; i < ret; i++){ if (token[i].type == JSMN_OBJECT) continue; if (jsoneq(jsonData, &token[i],"accel_devices") == 0){ int j; int numDevices = token[i+1].size; acapd_device_t *devs; devs = (acapd_device_t *)calloc(numDevices, sizeof(*devs)); if (devs == NULL) { acapd_perror("%s: Failed to alloc mem for accel devs.\n", __func__); ret = -ENOMEM; goto error; } i+=2; accel->num_ip_devs = numDevices; for(j=0; j < numDevices; j++){ if (jsoneq(jsonData, &token[i+j+1],"dev_name") == 0){ devs[j].dev_name = strndup(jsonData+token[i+j+2].start, token[i+j+2].end - token[i+j+2].start); } if (jsoneq(jsonData, &token[i+j+3],"reg_base") == 0) devs[j].reg_pa = (uint64_t)strtoll(strndup(jsonData+token[i+j+4].start, token[i+j+4].end - token[i+j+4].start), NULL, 16); if (jsoneq(jsonData, &token[i+j+5],"reg_size") == 0) devs[j].reg_size = (size_t)strtoll(strndup(jsonData+token[i+j+6].start, token[i+j+6].end - token[i+j+6].start), NULL, 16); i+=6; } accel->ip_dev = devs; } if (jsoneq(jsonData, &token[i],"accel_reg_base") == 0){} if (jsoneq(jsonData, &token[i],"accel_reg_size") == 0){} if (jsoneq(jsonData, &token[i],"sizeInKB")== 0){} if (jsoneq(jsonData, &token[i],"sharedMemType") == 0){} if (jsoneq(jsonData, &token[i],"dma_dev_name") == 0) dma_dev->dev_name = strndup(jsonData+token[i+1].start, token[i+1].end - token[i+1].start); if (jsoneq(jsonData, &token[i],"dma_driver") == 0) dma_dev->driver = strndup(jsonData+token[i+1].start, token[i+1].end - token[i+1].start); if (jsoneq(jsonData, &token[i],"dma_reg_base") == 0){} if (jsoneq(jsonData, &token[i],"iommu_group") == 0) dma_dev->iommu_group = atoi(strndup(jsonData+token[i+1].start, token[i+1].end - token[i+1].start)); if (jsoneq(jsonData, &token[i],"max_buf_size") == 0) buff_size = atoi(strndup(jsonData+token[i+1].start, token[i+1].end - token[i+1].start)); if (jsoneq(jsonData, &token[i],"Bus") == 0){} if (jsoneq(jsonData, &token[i],"HWType") == 0) dma_ops = strndup(jsonData+token[i+1].start, token[i+1].end - token[i+1].start); if (jsoneq(jsonData, &token[i],"dataMoverCacheCoherent") == 0){} if (jsoneq(jsonData, &token[i],"dataMoverVirtualAddress") == 0){} if (jsoneq(jsonData, &token[i],"dataMoverChnls") == 0){ int j; int numChnls = token[i+1].size; acapd_chnl_t *chnls; chnls = (acapd_chnl_t *)calloc(numChnls, sizeof(*chnls)); if (chnls == NULL) { acapd_perror("%s: failed to alloc mem for chnls.\n", __func__); ret = -ENOMEM; goto error; } i+=2; for(j=0; j < numChnls; j++){ if (jsoneq(jsonData, &token[i+j+1],"chnl_id") == 0){ chnls[j].chnl_id = atoi(strndup(jsonData+token[i+j+2].start, token[i+j+2].end - token[i+j+2].start)); } if (jsoneq(jsonData, &token[i+j+3],"chnl_dir") == 0){ char *dir = strndup(jsonData+token[i+j+4].start, token[i+j+4].end - token[i+j+4].start); if (!strcmp(dir,"ACAPD_DMA_DEV_R")) chnls[j].dir = ACAPD_DMA_DEV_R; else if (!strcmp(dir,"ACAPD_DMA_DEV_W")) chnls[j].dir = ACAPD_DMA_DEV_W; else if (!strcmp(dir,"ACAPD_DMA_DEV_RW")) chnls[j].dir = ACAPD_DMA_DEV_RW; } chnls[j].dev = dma_dev; chnls[j].max_buf_size = buff_size; if (!strcmp(dma_ops,"axidma")) chnls[j].ops = &axidma_vfio_dma_ops; else if (!strcmp(dma_ops,"mcdma")) chnls[j].ops = &mcdma_vfio_dma_ops; i+=4;//move token to point to next channel in array } accel->num_chnls = numChnls; accel->chnls = chnls; } if (jsoneq(jsonData, &token[i],"AccelHandshakeType") == 0){} if (jsoneq(jsonData, &token[i],"fallbackBehaviour") == 0){} } return 0; error: if (dma_dev != NULL) { free(dma_dev); } if (accel->ip_dev != NULL) { free(accel->ip_dev); accel->ip_dev = NULL; accel->num_ip_devs = 0; } if (accel->chnls != NULL) { free(accel->chnls); accel->chnls = NULL; accel->num_chnls = 0; } return ret; } int parseShellJson(acapd_shell_t *shell, const char *filename) { long numBytes; jsmn_parser parser; jsmntok_t token[128]; int ret,i; char *jsonData; struct stat s; FILE *fptr; fptr = fopen(filename, "r"); if (fptr == NULL){ acapd_perror("%s: Cannot open %s\n",__func__,filename); return -1; } acapd_device_t *dev; acapd_device_t *clk_dev; acapd_assert(shell != NULL); acapd_assert(filename != NULL); if (stat(filename,&s) != 0 || !S_ISREG(s.st_mode)){ acapd_perror("could not open %s\n",filename); return -1; } numBytes = s.st_size; jsonData = (char *)calloc(numBytes, sizeof(char)); if (jsonData == NULL) return -1; ret = fread(jsonData, sizeof(char), numBytes, fptr); if (ret < numBytes) acapd_perror("%s: Error reading Shell.json\n",__func__); fclose(fptr); jsmn_init(&parser); ret = jsmn_parse(&parser, jsonData, numBytes, token, sizeof(token)/sizeof(token[0])); if (ret < 0){ acapd_perror("Failed to parse JSON: %d\n", ret); } dev = &shell->dev; clk_dev = &shell->clock_dev; for(i=1; i < ret; i++){ if (token[i].type == JSMN_OBJECT) continue; if (jsoneq(jsonData, &token[i],"device_name") == 0) dev->dev_name = strndup(jsonData+token[i+1].start, token[i+1].end - token[i+1].start); if (jsoneq(jsonData, &token[i],"shell_type") == 0) { } if (jsoneq(jsonData, &token[i],"reg_base")== 0) dev->reg_pa = (uint64_t)strtol(strndup(jsonData+token[i+1].start, token[i+1].end - token[i+1].start), NULL, 16); if (jsoneq(jsonData, &token[i],"reg_size") == 0) dev->reg_size = (size_t)strtol(strndup(jsonData+token[i+1].start, token[i+1].end - token[i+1].start), NULL, 16); if (jsoneq(jsonData, &token[i],"clock_device_name") == 0) clk_dev->dev_name = strndup(jsonData+token[i+1].start, token[i+1].end - token[i+1].start); if (jsoneq(jsonData, &token[i],"clock_reg_base")== 0) clk_dev->reg_pa = (uint64_t)strtol(strndup(jsonData+token[i+1].start, token[i+1].end - token[i+1].start), NULL, 16); if (jsoneq(jsonData, &token[i],"clock_reg_size") == 0) clk_dev->reg_size = (size_t)strtol(strndup(jsonData+token[i+1].start, token[i+1].end - token[i+1].start), NULL, 16); if (jsoneq(jsonData, &token[i],"isolation_slots") == 0){ int j; if(token[i+1].type != JSMN_ARRAY) { acapd_perror("shell.json slots expects an array \n"); continue; } int numSlots = token[i+1].size; acapd_shell_regs_t *slot_regs; slot_regs = (acapd_shell_regs_t *)calloc(numSlots, sizeof(*slot_regs)); if (slot_regs == NULL) { acapd_perror("%s: failed to alloc mem for slot regs.\n", __func__); ret = -ENOMEM; } i+=3; for(j=0; j < numSlots; j++){ if (jsoneq(jsonData, &token[i+j],"offset") == 0){ int k; if(token[i+j+1].type != JSMN_ARRAY) { acapd_perror("shell.json offset expects an array \n"); continue; } slot_regs[j].offset = (uint32_t *)calloc(token[i+j+1].size, sizeof(uint32_t *)); for (k = 0; k < token[i+j+1].size; k++){ slot_regs[j].offset[k] = (uint32_t)strtol(strndup(jsonData+token[i+j+k+2].start, token[i+j+k+2].end - token[i+j+k+2].start), NULL, 16); } i += token[i+j+1].size;//increment by number of elements in offset array } if (jsoneq(jsonData, &token[i+j+2],"values") == 0){ int k; if(token[i+j+3].type != JSMN_ARRAY) { acapd_perror("shell.json values expects an array \n"); continue; } slot_regs[j].values = (uint32_t *)calloc(token[i+j+3].size, sizeof(uint32_t *)); for (k = 0; k < token[i+j+3].size; k++){ slot_regs[j].values[k] = (uint32_t)strtol(strndup(jsonData+token[i+j+k+4].start, token[i+j+k+4].end - token[i+j+k+4].start), NULL, 16); } i += token[i+j+3].size;//increment by number of elements in offset array } i+=4;//increment to point to next slot } shell->slot_regs = slot_regs; } } free(jsonData); return 0; } int initBaseDesign(struct basePLDesign *base, const char *shell_path) { long numBytes; jsmn_parser parser; jsmntok_t token[128]; int ret,i; char *jsonData; struct stat s; FILE *fptr; fptr = fopen(shell_path, "r"); if (fptr == NULL){ acapd_perror("%s: Cannot open %s\n",__func__,shell_path); return -1; } acapd_assert(shell_path != NULL); if (stat(shell_path,&s) != 0 || !S_ISREG(s.st_mode)){ acapd_perror("could not open %s\n",shell_path); return -1; } numBytes = s.st_size; jsonData = (char *)calloc(numBytes, sizeof(char)); if (jsonData == NULL){ acapd_perror("%s: calloc failed\n",__func__); return -1; } ret = fread(jsonData, sizeof(char), numBytes, fptr); if (ret < numBytes) acapd_perror("%s: Error reading Shell.json\n",__func__); fclose(fptr); jsmn_init(&parser); ret = jsmn_parse(&parser, jsonData, numBytes, token, sizeof(token)/sizeof(token[0])); if (ret < 0){ acapd_perror("Failed to parse JSON: %d\n", ret); } base->load_base_design = 1; base->num_pl_slots = 0; base->num_aie_slots = 0; for(i=1; i < ret; i++){ if (token[i].type == JSMN_OBJECT) continue; if (jsoneq(jsonData, &token[i],"shell_type") == 0) { int sz = MIN(token[i+1].end - token[i+1].start, sizeof(base->type)-1); strncpy(base->type, jsonData + token[i+1].start, sz); base->type[sz] = 0; if(strcmp(base->type,"XRT_FLAT") && strcmp(base->type,"PL_FLAT") && strcmp(base->type,"PL_DFX")) acapd_perror("shell_type valid types are XRT_FLAT/PL_FLAT/PL_DFX\n"); } if (jsoneq(jsonData, &token[i],"num_pl_slots") == 0) { base->num_pl_slots = strtol(jsonData+token[i+1].start, NULL, 10); } if (jsoneq(jsonData, &token[i],"num_aie_slots") == 0) { base->num_aie_slots = strtol(jsonData+token[i+1].start, NULL, 10); } if (jsoneq(jsonData, &token[i],"uid") == 0) { base->uid = strtol(jsonData+token[i+1].start, NULL, 16); } if (!jsoneq(jsonData, &token[i], "rp_comms_interconnect")) rp_comms_inter(base, jsonData, &token[i+1]); if (jsoneq(jsonData, &token[i],"load_base_design") == 0) { char *p = jsonData + token[i+1].start; // If "no" or "No" if ((p[0] == 'n' || p[0] == 'N') && p[1] == 'o') base->load_base_design = 0; } } if (!strcmp(base->type,"XRT_FLAT") || !strcmp(base->type,"PL_FLAT")) base->num_pl_slots = 1; free(jsonData); return 0; } int initAccel(accel_info_t *accel, const char *path) { long numBytes; jsmn_parser parser; jsmntok_t token[128]; int ret,i; char *jsonData; char json_path[256]; struct stat s; FILE *fptr; acapd_assert(path != NULL); sprintf(json_path,"%s/accel.json",path); fptr = fopen(json_path, "r"); if (fptr == NULL){ acapd_perror("%s: Cannot open %s\n",__func__,json_path); return -1; } if (stat(json_path,&s) != 0 || !S_ISREG(s.st_mode)){ acapd_perror("could not open %s\n",json_path); return -1; } numBytes = s.st_size; jsonData = (char *)calloc(numBytes, sizeof(char)); if (jsonData == NULL){ acapd_perror("%s: calloc failed\n",__func__); return -1; } ret = fread(jsonData, sizeof(char), numBytes, fptr); if (ret < numBytes) acapd_perror("%s: Error reading accel.json\n",__func__); fclose(fptr); jsmn_init(&parser); ret = jsmn_parse(&parser, jsonData, numBytes, token, sizeof(token)/sizeof(token[0])); if (ret < 0){ acapd_perror("Failed to parse JSON: %d\n", ret); } for(i=1; i < ret; i++){ if (token[i].type == JSMN_OBJECT) continue; if (jsoneq(jsonData, &token[i],"accel_type") == 0) { int sz = MIN(token[i+1].end - token[i+1].start, sizeof(accel->accel_type)-1); strncpy(accel->accel_type, jsonData + token[i+1].start, sz); accel->accel_type[sz] = 0; if(strcmp(accel->accel_type,"SIHA_PL_DFX") && strcmp(accel->accel_type, "XRT_AIE_DFX") && strcmp(accel->accel_type,"XRT_PL_DFX")) acapd_perror("accel_type valid values are SIHA_PL_DFX/XRT_AIE_DFX/XRT_PL_DFX\n"); } /* unique_id, parent_unique_id : uid, pid in base 16 w/ "0x" * or "0X" prefix to match data format produced by Vivado. */ if (!jsoneq(jsonData, &token[i], "uid")) accel->uid = strtol(jsonData+token[i+1].start, NULL, 16); if (!jsoneq(jsonData, &token[i], "pid")) accel->pid = strtol(jsonData+token[i+1].start, NULL, 16); } free(jsonData); return 0; } void parse_config(char *config_path, struct daemon_config *config) { long numBytes; jsmn_parser parser; jsmntok_t token[128]; int ret,i; char *jsonData; struct stat s; FILE *fptr; fptr = fopen(config_path, "r"); if (fptr == NULL){ acapd_perror("%s: Cannot open %s, it is required\n",__func__,config_path); return; } memset(config, 0, sizeof(struct daemon_config)); if (stat(config_path,&s) != 0 || !S_ISREG(s.st_mode)){ acapd_perror("could not open %s\n",config_path); return; } numBytes = s.st_size; jsonData = (char *)calloc(numBytes, sizeof(char)); if (jsonData == NULL){ acapd_perror("%s: calloc failed\n",__func__); return; } ret = fread(jsonData, sizeof(char), numBytes, fptr); if (ret < numBytes) acapd_perror("%s: Error reading %s\n",__func__,config_path); fclose(fptr); jsmn_init(&parser); ret = jsmn_parse(&parser, jsonData, numBytes, token, sizeof(token)/sizeof(token[0])); if (ret < 0){ acapd_perror("Failed to parse %s: %d\n",config_path, ret); } for(i=1; i < ret; i++){ if (token[i].type == JSMN_OBJECT) continue; if (jsoneq(jsonData, &token[i],"default_accel") == 0) { char *filename = strndup(jsonData+token[i+1].start, token[i+1].end - token[i+1].start); fptr = fopen(filename, "r"); free(filename); if (fptr == NULL) continue; ret = fscanf(fptr,"%s",config->defaul_accel_name); fclose(fptr); } if (jsoneq(jsonData, &token[i],"firmware_location") == 0){ int k; if(token[i+1].type != JSMN_ARRAY) { acapd_perror("%s firmware_location expects array \n",config_path); continue; } config->firmware_locations = (char **)calloc(token[i+1].size, MAX_PATH_SIZE*sizeof(char)); for (k = 0; k < token[i+1].size; k++){ config->firmware_locations[k] = strndup(jsonData+token[i+k+2].start, token[i+k+2].end - token[i+k+2].start); } config->number_locations=token[i+1].size; i += token[i+1].size;//increment by number of elements in array } } free(jsonData); return; } dfx-mgr-xilinx_v2023.2/src/sys/linux/print.c000066400000000000000000000016221446677152000210100ustar00rootroot00000000000000/* * Copyright (c) 2021, Xilinx Inc. and Contributors. All rights reserved. * * SPDX-License-Identifier: MIT */ #include #include #include #include #include #ifdef DEBUG void acapd_debug(const char *format, ...) { va_list argptr; va_start(argptr, format); fprintf(stdout, "DFX-MGRD> DEBUG: " ); vfprintf(stdout, format, argptr); fprintf(stdout, "\n" ); va_end(argptr); } #endif void acapd_print(const char *format, ...) { va_list argptr; va_start(argptr, format); fprintf(stdout, "DFX-MGRD> " ); vfprintf(stdout, format, argptr); fprintf(stdout, "\n" ); va_end(argptr); } void acapd_perror(const char *format, ...) { int errnum = errno; va_list argptr; va_start(argptr, format); fprintf(stderr, "DFX-MGRD> ERROR: " ); vfprintf(stderr, format, argptr); fprintf(stderr, "%s\n", errnum ? strerror(errnum) : ""); va_end(argptr); } dfx-mgr-xilinx_v2023.2/src/sys/linux/shell.c000066400000000000000000000016751446677152000207730ustar00rootroot00000000000000/* * Copyright (c) 2021, Xilinx Inc. and Contributors. All rights reserved. * * SPDX-License-Identifier: MIT */ #include #include #include #include #include #include #include #include #include int sys_shell_config(acapd_shell_t *shell, const char *config) { int ret; if (config != NULL) { if (access(config, F_OK) != 0) { acapd_debug("%s: config %s doesn't exist, check config env.\n", __func__, config); } } if (config == NULL) { config = getenv("ACAPD_SHELL_CONFIG"); } if (config == NULL || access(config, F_OK) != 0) { config = "./shell.json"; } if (access(config, F_OK) == 0) { ret = parseShellJson(shell, config); if (ret < 0) { acapd_perror("%s: failed to parse Shell json %s.\n", __func__, config); return ACAPD_ACCEL_FAILURE; } } return ACAPD_ACCEL_SUCCESS; } dfx-mgr-xilinx_v2023.2/src/sys/linux/shm.c000066400000000000000000000025551446677152000204510ustar00rootroot00000000000000/* * Copyright (c) 2021, Xilinx Inc. and Contributors. All rights reserved. * * SPDX-License-Identifier: MIT */ #include #include #include #include #include #include #include static int acapd_vfio_alloc_shm(acapd_shm_allocator_t *allocator, acapd_shm_t *shm, size_t size, uint32_t attr) { (void)allocator; (void)attr; if (shm == NULL) { acapd_perror("%s: shm is NULL.\n", __func__); return -EINVAL; } if (shm->id < 0) { shm->id = 0; } if (shm->flags == 0) { shm->flags = MAP_PRIVATE | MAP_ANONYMOUS; } shm->va = mmap(NULL, size, PROT_READ | PROT_WRITE, shm->flags, shm->id, 0); if (shm->va == MAP_FAILED) { acapd_perror("%s: failed to allocate memory from fd %d, %s.\n", __func__, shm->id, strerror(errno)); } else { acapd_debug("%s: allocated memory %p from fd %d.\n", __func__, shm->va, shm->id); } shm->size = size; return 0; } static void acapd_vfio_free_shm(acapd_shm_allocator_t *allocator, acapd_shm_t *shm) { (void)allocator; if (shm == NULL) { acapd_perror("%s: error, shm is NULL.\n", __func__); return; } (void)munmap(shm->va, shm->size); } acapd_shm_allocator_t acapd_default_shm_allocator = { .name = "vfio_shm_allocator", .priv = NULL, .alloc = acapd_vfio_alloc_shm, .free = acapd_vfio_free_shm, };