/* * Copyright (C) 2017-2018 Xilinx, Inc * Author: Sonal Santan * AWS HAL Driver for SDAccel/OpenCL runtime evnrionemnt, for AWS EC2 F1 * * Code copied from SDAccel XDMA based HAL driver * * Licensed under the Apache License, Version 2.0 (the "License"). You may * not use this file except in compliance with the License. A copy of the * License is located at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the * License for the specific language governing permissions and limitations * under the License. */ #include "shim.h" #include <errno.h> /* * Define GCC version macro so we can use newer C++11 features * if possible */ #define GCC_VERSION (__GNUC__ * 10000 \ + __GNUC_MINOR__ * 100 \ + __GNUC_PATCHLEVEL__) #ifdef INTERNAL_TESTING #define ACCELERATOR_BAR 0 #define MMAP_SIZE_USER 0x400000 #endif /* Aligning access to FPGA DRAM space to 4096 Byte */ #define DDR_BUFFER_ALIGNMENT 0x1000 #include <sys/types.h> #include <sys/mman.h> #include <unistd.h> #include <sys/stat.h> #include <fcntl.h> #include <sys/ioctl.h> #include <sys/file.h> #include <cstdio> #include <cstring> #include <cassert> #include <algorithm> #include <stdlib.h> #include <thread> #include <chrono> #include <iostream> #include <fstream> #include <mutex> #include "xclbin.h" #include "xocl/xocl_ioctl.h" #include "scan.h" #include "awssak.h" #ifdef INTERNAL_TESTING #include "driver/aws/kernel/include/mgmt-ioctl.h" #else #define AWSMGMT_NUM_SUPPORTED_CLOCKS 4 #define AWSMGMT_NUM_ACTUAL_CLOCKS 3 // TODO - define this in a header file extern char* get_afi_from_xclBin(const xclBin *); extern char* get_afi_from_axlf(const axlf *); // define DEFAULT_GLOBAL_AFI "agfi-069ddd533a748059b" // 1.4 shell #define DEFAULT_GLOBAL_AFI "agfi-0cc0ac6a40aa73ce8" // 1.4 shell 4-ddr data retention enabled #endif namespace awsbwhal { // This list will get populated in xclProbe // 0 -> /dev/dri/renderD129 // 1 -> /dev/dri/renderD130 static std::mutex deviceListMutex; // static std::vector<std::pair<int, int>> deviceList; const unsigned AwsXcl::TAG = 0X586C0C6C; // XL OpenCL X->58(ASCII), L->6C(ASCII), O->0 C->C L->6C(ASCII); #ifdef INTERNAL_TESTING int AwsXcl::xclLoadAxlf(const axlf *buffer) { if ( mLogStream.is_open()) { mLogStream << __func__ << ", " << std::this_thread::get_id() << ", " << buffer << std::endl; } if ( !mLocked) return -EPERM; std::cout << "Downloading xclbin ...\n" << std::endl; const unsigned cmd = AWSMGMT_IOCICAPDOWNLOAD_AXLF; awsmgmt_ioc_bitstream_axlf obj = { const_cast<axlf *>(buffer) }; int ret = ioctl(mMgtHandle, cmd, &obj); if ( 0 != ret) return ret; // If it is an XPR DSA, zero out the DDR again as downloading the XCLBIN // reinitializes the DDR and results in ECC error. if ( isXPR()) { if ( mLogStream.is_open()) { mLogStream << __func__ << "XPR Device found, zeroing out DDR again.." << std::endl; } if ( zeroOutDDR() == false) { if ( mLogStream.is_open()) { mLogStream << __func__ << "zeroing out DDR failed" << std::endl; } return -EIO; } } drm_xocl_axlf axlf_obj = {const_cast<axlf *>(buffer)}; ret = ioctl(mUserHandle, DRM_IOCTL_XOCL_READ_AXLF, &axlf_obj); return ret; } #endif int AwsXcl::xclGetXclBinIdFromSysfs(uint64_t &xclbin_id_from_sysfs) { const std::string devPath = "/sys/bus/pci/devices/" + xcldev::pci_device_scanner::device_list[ mBoardNumber ].user_name; std::string binid_path = devPath + "/xclbinid"; struct stat sb; if( stat( binid_path.c_str(), &sb ) < 0 ) { std::cout << "ERROR: failed to stat " << binid_path << std::endl; return errno; } std::ifstream ifs( binid_path.c_str(), std::ifstream::binary ); if( !ifs.good() ) { return errno; } char* fileReadBuf = new char[sb.st_size]; memset(fileReadBuf, 0, sb.st_size); ifs.read( fileReadBuf, sb.st_size ); if( ifs.gcount() > 0 ) { std::string tmp_hex_string = fileReadBuf; xclbin_id_from_sysfs = std::stoi(std::string(fileReadBuf),nullptr,16); } else { // xclbinid exists, but no data read or reported std::cout << "WARNING: 'xclbinid' invalid, unable to report xclbinid. Has the bitstream been loaded? See 'xbsak program'.\n"; } delete [] fileReadBuf; ifs.close(); return 0; } int AwsXcl::xclLoadXclBin(const xclBin *buffer) { char *xclbininmemory = reinterpret_cast<char*> (const_cast<xclBin*> (buffer)); #ifdef INTERNAL_TESTING if (!memcmp(xclbininmemory, "xclbin2", 8)) { return xclLoadAxlf(reinterpret_cast<axlf*>(xclbininmemory)); } if (mLogStream.is_open()) { mLogStream << __func__ << ", " << std::this_thread::get_id() << ", " << buffer << std::endl; } if (!mLocked) return -EPERM; const unsigned cmd = AWSMGMT_IOCICAPDOWNLOAD; awsmgmt_ioc_bitstream obj = {const_cast<xclBin *>(buffer)}; return ioctl(mMgtHandle, cmd, &obj); #else if (!memcmp(xclbininmemory, "xclbin2", 8)) { int retVal = 0; axlf *axlfbuffer = reinterpret_cast<axlf*>(const_cast<xclBin*> (buffer)); fpga_mgmt_image_info orig_info; char* afi_id = get_afi_from_axlf(axlfbuffer); std::memset(&orig_info, 0, sizeof(struct fpga_mgmt_image_info)); fpga_mgmt_describe_local_image(mBoardNumber, &orig_info, 0); uint64_t xclbin_id_from_sysfs; if( int retVal = xclGetXclBinIdFromSysfs( xclbin_id_from_sysfs ) != 0 ) return retVal; if ( (xclbin_id_from_sysfs == 0) || (axlfbuffer->m_uniqueId != xclbin_id_from_sysfs) || checkAndSkipReload(afi_id, &orig_info) ) { // force data retention option union fpga_mgmt_load_local_image_options opt; fpga_mgmt_init_load_local_image_options(&opt); opt.flags = FPGA_CMD_DRAM_DATA_RETENTION; opt.afi_id = afi_id; opt.slot_id = mBoardNumber; retVal = fpga_mgmt_load_local_image_with_options(&opt); if (retVal == FPGA_ERR_DRAM_DATA_RETENTION_NOT_POSSIBLE || retVal == FPGA_ERR_DRAM_DATA_RETENTION_FAILED || retVal == FPGA_ERR_DRAM_DATA_RETENTION_SETUP_FAILED) { std::cout << "INFO: Could not load AFI for data retention, code: " << retVal << " - Loading in classic mode." << std::endl; retVal = fpga_mgmt_load_local_image(mBoardNumber, afi_id); } // check retVal from image load if (retVal) { std::cout << "Failed to load AFI, error: " << retVal << std::endl; return -retVal; } retVal = sleepUntilLoaded( std::string(afi_id) ); if (!retVal) { drm_xocl_axlf axlf_obj = { reinterpret_cast<axlf*>(const_cast<xclBin*>(buffer)) }; retVal = ioctl(mUserHandle, DRM_IOCTL_XOCL_READ_AXLF, &axlf_obj); if (retVal) { std::cout << "IOCTL DRM_IOCTL_XOCL_READ_AXLF Failed: " << retVal << std::endl; } else { std::cout << "AFI load complete." << std::endl; } } } return retVal; } else { char* afi_id = get_afi_from_xclBin(buffer); return fpga_mgmt_load_local_image(mBoardNumber, afi_id); } #endif } /* Accessing F1 FPGA memory space (i.e. OpenCL Global Memory) is mapped through AppPF BAR4 * all offsets are relative to the base address available in AppPF BAR4 * SDAcell XCL_ADDR_SPACE_DEVICE_RAM enum maps to AwsXcl::ocl_global_mem_bar, which is the * handle for AppPF BAR4 */ size_t AwsXcl::xclReadModifyWrite(uint64_t offset, const void *hostBuf, size_t size) { if (mLogStream.is_open()) { mLogStream << __func__ << ", " << std::this_thread::get_id() << ", " << offset << ", " << hostBuf << ", " << size << std::endl; } #if GCC_VERSION >= 40800 alignas(DDR_BUFFER_ALIGNMENT) char buffer[DDR_BUFFER_ALIGNMENT]; #else AlignedAllocator<char> alignedBuffer(DDR_BUFFER_ALIGNMENT, DDR_BUFFER_ALIGNMENT); char* buffer = alignedBuffer.getBuffer(); #endif const size_t mod_size = offset % DDR_BUFFER_ALIGNMENT; // Read back one full aligned block starting from preceding aligned address const uint64_t mod_offset = offset - mod_size; if (xclRead(XCL_ADDR_SPACE_DEVICE_RAM, mod_offset, buffer, DDR_BUFFER_ALIGNMENT) != DDR_BUFFER_ALIGNMENT) return -1; // Update the local copy of buffer with user requested data const size_t copy_size = (size + mod_size > DDR_BUFFER_ALIGNMENT) ? DDR_BUFFER_ALIGNMENT - mod_size : size; std::memcpy(buffer + mod_size, hostBuf, copy_size); // Write back the updated aligned block if (xclWrite(XCL_ADDR_SPACE_DEVICE_RAM, mod_offset, buffer, DDR_BUFFER_ALIGNMENT) != DDR_BUFFER_ALIGNMENT) return -1; // Write any remaining blocks over DDR_BUFFER_ALIGNMENT size if (size + mod_size > DDR_BUFFER_ALIGNMENT) { size_t write_size = xclWrite(XCL_ADDR_SPACE_DEVICE_RAM, mod_offset + DDR_BUFFER_ALIGNMENT, (const char *)hostBuf + copy_size, size - copy_size); if (write_size != (size - copy_size)) return -1; } return size; } /* Accessing F1 FPGA memory space mapped through AppPF PCIe BARs * space = XCL_ADDR_SPACE_DEVICE_RAM maps to AppPF PCIe BAR4, (sh_cl_dma_pcis_ bus), with AwsXcl::ocl_global_mem_bar as handle * space = XCL_ADDR_KERNEL_CTRL maps to AppPF PCIe BAR0 (sh_cl_ocl bus), with AwsXcl::ocl_kernel_bar as handle * all offsets are relative to the base address available in AppPF */ size_t AwsXcl::xclWrite(xclAddressSpace space, uint64_t offset, const void *hostBuf, size_t size) { if (mLogStream.is_open()) { mLogStream << __func__ << ", " << std::this_thread::get_id() << ", " << space << ", " << offset << ", " << hostBuf << ", " << size << std::endl; } if (!mLocked) return -1; switch (space) { /* Current release now includes performance monitors */ case XCL_ADDR_SPACE_DEVICE_PERFMON: { #ifdef INTERNAL_TESTING if (pcieBarWrite(ACCELERATOR_BAR, offset, hostBuf, size) == 0) { return size; } #else if (pcieBarWrite(APP_PF_BAR0, offset, hostBuf, size) == 0) { return size; } #endif return -1; } case XCL_ADDR_KERNEL_CTRL: { if (mLogStream.is_open()) { const unsigned *reg = static_cast<const unsigned *>(hostBuf); size_t regSize = size / 4; if (regSize > 32) regSize = 32; for (unsigned i = 0; i < regSize; i++) { mLogStream << __func__ << ", " << std::this_thread::get_id() << ", " << space << ", 0x" << std::hex << offset + i << std::dec << ", 0x" << std::hex << reg[i] << std::dec << std::endl; } } #ifdef INTERNAL_TESTING if (pcieBarWrite(ACCELERATOR_BAR, offset, hostBuf, size) == 0) { #else if (pcieBarWrite(APP_PF_BAR0, offset, hostBuf, size) == 0) { #endif return size; } return -1; } default: { return -1; } } } size_t AwsXcl::xclRead(xclAddressSpace space, uint64_t offset, void *hostBuf, size_t size) { if (mLogStream.is_open()) { mLogStream << __func__ << ", " << std::this_thread::get_id() << ", " << space << ", " << offset << ", " << hostBuf << ", " << size << std::endl; } switch (space) { case XCL_ADDR_SPACE_DEVICE_PERFMON: { #ifdef INTERNAL_TESTING if (pcieBarRead(ACCELERATOR_BAR, offset, hostBuf, size) == 0) { return size; } #else if (pcieBarRead(APP_PF_BAR0, offset, hostBuf, size) == 0) { return size; } #endif return -1; } case XCL_ADDR_KERNEL_CTRL: { #ifdef INTERNAL_TESTING int result = pcieBarRead(ACCELERATOR_BAR, offset, hostBuf, size); #else int result = pcieBarRead(APP_PF_BAR0, offset, hostBuf, size); #endif if (mLogStream.is_open()) { const unsigned *reg = static_cast<const unsigned *>(hostBuf); size_t regSize = size / 4; if (regSize > 4) regSize = 4; for (unsigned i = 0; i < regSize; i++) { mLogStream << __func__ << ", " << std::this_thread::get_id() << ", " << space << ", 0x" << std::hex << offset + i << std::dec << ", 0x" << std::hex << reg[i] << std::dec << std::endl; } } return !result ? size : 0; } default: { return -1; } } } uint64_t AwsXcl::xclAllocDeviceBuffer(size_t size) { if (mLogStream.is_open()) { mLogStream << __func__ << ", " << std::this_thread::get_id() << ", " << size << std::endl; } uint64_t result = mNullAddr; unsigned boHandle = xclAllocBO(size, XCL_BO_DEVICE_RAM, 0x0); if (boHandle == mNullBO) return result; drm_xocl_info_bo boInfo = {boHandle, 0, 0, 0}; if (ioctl(mUserHandle, DRM_IOCTL_XOCL_INFO_BO, &boInfo)) return result; void *hbuf = xclMapBO(boHandle, true); if (hbuf == MAP_FAILED) { xclFreeBO(boHandle); return mNullAddr; } mLegacyAddressTable.insert(boInfo.paddr, size, std::make_pair(boHandle, (char *)hbuf)); return boInfo.paddr; } uint64_t AwsXcl::xclAllocDeviceBuffer2(size_t size, xclMemoryDomains domain, unsigned flags) { if (mLogStream.is_open()) { mLogStream << __func__ << ", " << std::this_thread::get_id() << ", " << size << ", " << domain << ", " << flags << std::endl; } uint64_t result = mNullAddr; if (domain != XCL_MEM_DEVICE_RAM) return result; unsigned ddr = 1; ddr <<= flags; unsigned boHandle = xclAllocBO(size, XCL_BO_DEVICE_RAM, ddr); if (boHandle == mNullBO) return result; drm_xocl_info_bo boInfo = {boHandle, 0, 0, 0}; if (ioctl(mUserHandle, DRM_IOCTL_XOCL_INFO_BO, &boInfo)) return result; void *hbuf = xclMapBO(boHandle, true); if (hbuf == MAP_FAILED) { xclFreeBO(boHandle); return mNullAddr; } mLegacyAddressTable.insert(boInfo.paddr, size, std::make_pair(boHandle, (char *)hbuf)); return boInfo.paddr; } void AwsXcl::xclFreeDeviceBuffer(uint64_t buf) { if (mLogStream.is_open()) { mLogStream << __func__ << ", " << std::this_thread::get_id() << ", " << buf << std::endl; } std::pair<unsigned, char *> bo = mLegacyAddressTable.erase(buf); drm_xocl_info_bo boInfo = {bo.first, 0, 0, 0}; if (!ioctl(mUserHandle, DRM_IOCTL_XOCL_INFO_BO, &boInfo)) { munmap(bo.second, boInfo.size); } xclFreeBO(bo.first); } size_t AwsXcl::xclCopyBufferHost2Device(uint64_t dest, const void *src, size_t size, size_t seek) { if (mLogStream.is_open()) { mLogStream << __func__ << ", " << std::this_thread::get_id() << ", " << dest << ", " << src << ", " << size << ", " << seek << std::endl; } std::pair<unsigned, char *> bo = mLegacyAddressTable.find(dest); std::memcpy(bo.second + seek, src, size); int result = xclSyncBO(bo.first, XCL_BO_SYNC_BO_TO_DEVICE, size, seek); if (result) return result; return size; } size_t AwsXcl::xclCopyBufferDevice2Host(void *dest, uint64_t src, size_t size, size_t skip) { if (mLogStream.is_open()) { mLogStream << __func__ << ", " << std::this_thread::get_id() << ", " << dest << ", " << src << ", " << size << ", " << skip << std::endl; } std::pair<unsigned, char *> bo = mLegacyAddressTable.find(src); int result = xclSyncBO(bo.first, XCL_BO_SYNC_BO_FROM_DEVICE, size, skip); if (result) return result; std::memcpy(dest, bo.second + skip, size); return size; } AwsXcl *AwsXcl::handleCheck(void *handle) { // Sanity checks if (!handle) return 0; if (*(unsigned *)handle != TAG) return 0; if (!((AwsXcl *)handle)->isGood()) { return 0; } return (AwsXcl *)handle; } unsigned AwsXcl::xclProbe() { std::lock_guard<std::mutex> lock(awsbwhal::deviceListMutex); if(xcldev::pci_device_scanner::device_list.size() == 0) { xcldev::pci_device_scanner devices; devices.scan(true); } unsigned i = 0; #ifdef INTERNAL_TESTING char file_name_buf[128]; for (i = 0; i < 16; i++) { std::sprintf((char *)&file_name_buf, "/dev/awsmgmt%d", i); int fd = open(file_name_buf, O_RDWR); if (fd < 0) { return i; } close(fd); } if (i != xcldev::pci_device_scanner::device_list.size()) { std::cout << "ERROR xclProbe: Num of FPGA userPF device do not match num of mgmtPF devices" << std::endl; std::cout << "ERROR xclProbe: Num of userPF, mgmtPF devices = " << std::dec << xcldev::pci_device_scanner::device_list.size() << std::dec << i << std::endl; return 0; } #endif i = xcldev::pci_device_scanner::device_list.size(); #ifndef INTERNAL_TESTING std::cout << "xclProbe found " << std::dec << i << " FPGA slots with xocl driver running" << std::endl; #else std::cout << "xclProbe found " << std::dec << i << " FPGA slots with awsmgmt & xocl driver running" << std::endl; #endif return i; } AwsXcl::~AwsXcl() { #ifdef INTERNAL_TESTING if (mUserMap != MAP_FAILED) { munmap(mUserMap, MMAP_SIZE_USER); } if (mUserHandle > 0) { close(mUserHandle); } if (mMgtHandle > 0) close(mMgtHandle); #else //# error "INTERNAL_TESTING macro disabled. AMZN code goes here. " if (ocl_kernel_bar >=0) fpga_pci_detach(ocl_kernel_bar); if (ocl_global_mem_bar>=0) fpga_pci_detach(ocl_global_mem_bar); if (sda_mgmt_bar>=0) fpga_pci_detach(sda_mgmt_bar); ocl_kernel_bar = -1; ocl_global_mem_bar = -1; sda_mgmt_bar = -1; #endif if (mLogStream.is_open()) { mLogStream << __func__ << ", " << std::this_thread::get_id() << std::endl; mLogStream.close(); } fpga_mgmt_close(); } AwsXcl::AwsXcl(unsigned index, const char *logfileName, xclVerbosityLevel verbosity) : mTag(TAG), mBoardNumber(index), maxDMASize(0xfa0000), mLocked(false), mOffsets{0x0, 0x0, 0x0, 0x0}, mOclRegionProfilingNumberSlots(XPAR_AXI_PERF_MON_2_NUMBER_SLOTS) { #ifndef INTERNAL_TESTING loadDefaultAfiIfCleared(); #endif const std::string devName = "/dev/dri/renderD" + std::to_string(xcldev::pci_device_scanner::device_list[mBoardNumber].user_instance); #ifndef INTERNAL_TESTING mUserHandle = open(devName.c_str(), O_RDWR); if(mUserHandle <= 0) { std::cout << "WARNING: AwsXcl - Cannot open userPF: " << devName << std::endl; } #endif fpga_mgmt_init(); #ifdef INTERNAL_TESTING if(mUserHandle > 0) { mUserMap = (char *)mmap(0, MMAP_SIZE_USER, PROT_READ | PROT_WRITE, MAP_SHARED, mUserHandle, 0); if (mUserMap == MAP_FAILED) { std::cout << "Map failed: " << devName << std::endl; close(mUserHandle); mUserHandle = -1; } } char file_name_buf[128]; std::fill(&file_name_buf[0], &file_name_buf[0] + 128, 0); std::sprintf((char *)&file_name_buf, "/dev/awsmgmt%d", mBoardNumber); mMgtHandle = open(file_name_buf, O_RDWR | O_SYNC); if(mMgtHandle > 0) { if (xclGetDeviceInfo2(&mDeviceInfo)) { close(mMgtHandle); mMgtHandle = -1; } } else { std::cout << "Cannot open mgmtPF: " << devName << std::endl; } #else int slot_id = mBoardNumber; ocl_kernel_bar = -1; ocl_global_mem_bar = -1; sda_mgmt_bar = -1; if (xclGetDeviceInfo2(&mDeviceInfo)) { std::cout << "ERROR AwsXcl: DeviceInfo failed for slot# " << std::dec << slot_id << std::endl; } else if (fpga_pci_attach(slot_id, FPGA_APP_PF, APP_PF_BAR0, 0, &ocl_kernel_bar) ) { ocl_kernel_bar = -1; std::cout << "ERROR AwsXcl: PCI kernel bar attach failed for slot# " << std::dec << slot_id << std::endl; } else if (fpga_pci_attach(slot_id, FPGA_APP_PF, APP_PF_BAR4, 0, &ocl_global_mem_bar) ) { fpga_pci_detach(ocl_kernel_bar); ocl_kernel_bar = -1; ocl_global_mem_bar = -1; sda_mgmt_bar = -1; std::cout << "ERROR AwsXcl: PCI global bar attach failed for slot# " << std::dec << slot_id << std::endl; } else if (fpga_pci_attach(slot_id, FPGA_MGMT_PF, MGMT_PF_BAR4, 0, &sda_mgmt_bar) ) { fpga_pci_detach(ocl_kernel_bar); fpga_pci_detach(ocl_global_mem_bar); ocl_kernel_bar = -1; ocl_global_mem_bar = -1; sda_mgmt_bar = -1; std::cout << "ERROR AwsXcl: PCI mgmt bar attach failed for slot# " << std::dec << slot_id << std::endl; } #endif // // Profiling - defaults // Class-level defaults: mIsDebugIpLayoutRead = mIsDeviceProfiling = false mDevUserName = xcldev::pci_device_scanner::device_list[mBoardNumber].user_name; mMemoryProfilingNumberSlots = 0; mPerfMonFifoCtrlBaseAddress = 0x00; mPerfMonFifoReadBaseAddress = 0x00; // // Profiling - defaults // Class-level defaults: mIsDebugIpLayoutRead = mIsDeviceProfiling = false mDevUserName = xcldev::pci_device_scanner::device_list[mBoardNumber].user_name; mMemoryProfilingNumberSlots = 0; mPerfMonFifoCtrlBaseAddress = 0x00; mPerfMonFifoReadBaseAddress = 0x00; // // Profiling - defaults // Class-level defaults: mIsDebugIpLayoutRead = mIsDeviceProfiling = false mDevUserName = xcldev::pci_device_scanner::device_list[mBoardNumber].user_name; mMemoryProfilingNumberSlots = 0; mPerfMonFifoCtrlBaseAddress = 0x00; mPerfMonFifoReadBaseAddress = 0x00; } bool AwsXcl::isGood() const { #ifdef INTERNAL_TESTING if (mUserHandle < 0) { std::cout << "AwsXcl: Bad handle. No userPF Handle" << std::endl; return false; } if (mMgtHandle < 0) { std::cout << "AwsXcl: Bad handle. No mgmtPF Handle" << std::endl; return false; } #else if (ocl_kernel_bar < 0) { std::cout << "WARNING: AwsXcl isGood: kernel, global & mgmt bar are: " << std::hex << ocl_kernel_bar << ", " << std::hex << ocl_global_mem_bar << ", " << sda_mgmt_bar << std::endl; return false; } if (ocl_global_mem_bar < 0) { std::cout << "WARNING: AwsXcl isGood: kernel, global & mgmt bar are: " << std::hex << ocl_kernel_bar << ", " << std::hex << ocl_global_mem_bar << ", " << sda_mgmt_bar << std::endl; return false; } if (sda_mgmt_bar < 0) { std::cout << "WARNING: AwsXcl isGood: kernel, global & mgmt bar are: " << std::hex << ocl_kernel_bar << ", " << std::hex << ocl_global_mem_bar << ", " << sda_mgmt_bar << std::endl; return false; } if (mUserHandle <= 0) { std::cout << "WARNING: AwsXcl isGood: invalid user handle." << std::endl; return false; } #endif return true; } int AwsXcl::pcieBarRead(int bar_num, unsigned long long offset, void* buffer, unsigned long long length) { char *qBuf = (char *)buffer; switch (bar_num) { #ifdef INTERNAL_TESTING const char *mem = 0; case 0: { if ((length + offset) > MMAP_SIZE_USER) { return -1; } mem = mUserMap; #else case APP_PF_BAR0: { #endif break; } default: { return -1; } } while (length >= 4) { #ifdef INTERNAL_TESTING *(unsigned *)qBuf = *(unsigned *)(mem + offset); #else fpga_pci_peek(ocl_kernel_bar, (uint64_t)offset,(uint32_t*)qBuf); #endif offset += 4; qBuf += 4; length -= 4; } while (length) { #ifdef INTERNAL_TESTING *qBuf = *(mem + offset); #else // TODO - add support for sub 4-byte read in AWS platform #endif offset++; qBuf++; length--; } // std::memcpy(buffer, mem + offset, length); return 0; } int AwsXcl::pcieBarWrite(int bar_num, unsigned long long offset, const void* buffer, unsigned long long length) { char *qBuf = (char *)buffer; switch (bar_num) { #ifdef INTERNAL_TESTING char *mem = 0; case 0: { if ((length + offset) > MMAP_SIZE_USER) { return -1; } mem = mUserMap; #else case APP_PF_BAR0: { #endif break; } default: { return -1; } } while (length >= 4) { #ifdef INTERNAL_TESTING *(unsigned *)(mem + offset) = *(unsigned *)qBuf; #else fpga_pci_poke(ocl_kernel_bar, uint64_t (offset), *((uint32_t*) qBuf)); #endif offset += 4; qBuf += 4; length -= 4; } while (length) { #ifdef INTERNEL_TESTING *(mem + offset) = *qBuf; #else std::cout << "xclWrite - unsupported write with length not multiple of 4-bytes" << std::endl; #endif offset++; qBuf++; length--; } // std::memcpy(mem + offset, buffer, length); return 0; } bool AwsXcl::zeroOutDDR() { // Zero out the FPGA external DRAM Content so memory controller // will not complain about ECC error from memory regions not // initialized before // In AWS F1 FPGA, the DRAM is clear before loading new AFI // hence this API is redundant and will return false to // make sure developers dont assume it works // static const unsigned long long BLOCK_SIZE = 0x4000000; // void *buf = 0; // if (posix_memalign(&buf, DDR_BUFFER_ALIGNMENT, BLOCK_SIZE)) // return false; // memset(buf, 0, BLOCK_SIZE); // mDataMover->pset64(buf, BLOCK_SIZE, 0, mDeviceInfo.mDDRSize/BLOCK_SIZE); // free(buf); return false; } /* Locks a given FPGA Slot * By levering the available lock infrastrucutre for the DMA * Driver associated with the given FPGA slot */ bool AwsXcl::xclLockDevice() { #ifdef INTERNAL_TESTING #else // FIXME: do we need to flock the ocl_kernel interface as well ? // #endif mLocked = true; // return zeroOutDDR(); return true; } std::string AwsXcl::getDSAName(unsigned short deviceId, unsigned short subsystemId) { std::string dsa("xilinx_aws-vu9p-f1-04261818_dynamic_5_0"); return dsa; } int AwsXcl::xclGetDeviceInfo2(xclDeviceInfo2 *info) { std::memset(info, 0, sizeof(xclDeviceInfo2)); info->mMagic = 0X586C0C6C; info->mHALMajorVersion = XCLHAL_MAJOR_VER; info->mHALMajorVersion = XCLHAL_MINOR_VER; info->mMinTransferSize = DDR_BUFFER_ALIGNMENT; info->mDMAThreads = 4;//AWS has four threads. Others have only two threads #ifdef INTERNAL_TESTING /* Sarab disabling xdma ioctl xdma_ioc_info obj = {{0X586C0C6C, XDMA_IOCINFO}}; /--* Calling the underlying DMA driver to extract * DMA specific configuration * A non-zero value reprent at error *--/ int ret = ioctl(mUserHandle, XDMA_IOCINFO, &obj); // Log the return value for further debug if (ret) return ret; info->mVendorId = obj.vendor; info->mDeviceId = obj.device; info->mSubsystemId = obj.subsystem_device; info->mSubsystemVendorId = obj.subsystem_vendor; info->mDeviceVersion = obj.subsystem_device & 0x00ff; */ awsmgmt_ioc_info mgmt_info_obj; int ret = ioctl(mMgtHandle, AWSMGMT_IOCINFO, &mgmt_info_obj); if (ret) return ret; info->mVendorId = mgmt_info_obj.vendor; info->mDeviceId = mgmt_info_obj.device; info->mSubsystemId = mgmt_info_obj.subsystem_device; info->mSubsystemVendorId = mgmt_info_obj.subsystem_vendor; info->mDeviceVersion = mgmt_info_obj.subsystem_device & 0x00ff; info->mPCIeLinkWidth = mgmt_info_obj.pcie_link_width; info->mPCIeLinkSpeed = mgmt_info_obj.pcie_link_speed; for (int i = 0; i < AWSMGMT_NUM_SUPPORTED_CLOCKS; ++i) { info->mOCLFrequency[i] = mgmt_info_obj.ocl_frequency[i]; } info->mMigCalib = true; for (int i = 0; i < 4; i++) { info->mMigCalib = info->mMigCalib && mgmt_info_obj.mig_calibration[i]; } #else struct fpga_slot_spec slot_info; //fpga_pci_get_slot_spec(mBoardNumber,FPGA_APP_PF, &slot_info); fpga_pci_get_slot_spec(mBoardNumber, &slot_info); info->mVendorId = slot_info.map[0].vendor_id; info->mDeviceId = slot_info.map[0].device_id; // FIXME - update next 3 variables info->mSubsystemId = slot_info.map[0].subsystem_device_id; info->mSubsystemVendorId = slot_info.map[0].subsystem_vendor_id; info->mDeviceVersion = 0; info->mPCIeLinkWidth = 16; info->mPCIeLinkSpeed = 8000; fpga_mgmt_image_info imageInfo; fpga_mgmt_describe_local_image( mBoardNumber, &imageInfo, 0 ); for (int i = 0; i < AWSMGMT_NUM_SUPPORTED_CLOCKS; ++i) { info->mOCLFrequency[i] = imageInfo.metrics.clocks[i].frequency[0] / 1000000; } info->mMigCalib = true; #endif // F1 has 16 GiB per channel info->mDDRSize = 0x400000000 * 4; info->mDataAlignment = DDR_BUFFER_ALIGNMENT; info->mNumClocks = AWSMGMT_NUM_ACTUAL_CLOCKS; // Number of available channels // TODO: add support for other FPGA configurations with less // than 4 DRAM channels info->mDDRBankCount = 4; const std::string deviceName = getDSAName(info->mDeviceId, info->mSubsystemId); if (mLogStream.is_open()) mLogStream << __func__ << ", " << std::this_thread::get_id() << ", " << deviceName << std::endl; std::size_t length = deviceName.copy(info->mName, deviceName.length(),0); info->mName[length] = '\0'; if (mLogStream.is_open()) { mLogStream << __func__ << ": name=" << deviceName << ", version=0x" << std::hex << info->mDeviceVersion << ", clock freq=" << std::dec << info->mOCLFrequency[0] << ", clock freq 2=" << std::dec << info->mOCLFrequency[1] << std::endl; } info->mOnChipTemp = 25; info->mFanTemp = 0; info->mVInt = 0.9; info->mVAux = 0.9; info->mVBram = 0.9; return 0; } int AwsXcl::resetDevice(xclResetKind kind) { // Call a new IOCTL to just reset the OCL region // if (kind == XCL_RESET_FULL) { // xdma_ioc_base obj = {0X586C0C6C, XDMA_IOCHOTRESET}; // return ioctl(mUserHandle, XDMA_IOCHOTRESET, &obj); // } // else if (kind == XCL_RESET_KERNEL) { // xdma_ioc_base obj = {0X586C0C6C, XDMA_IOCOCLRESET}; // return ioctl(mUserHandle, XDMA_IOCOCLRESET, &obj); // } // return -EINVAL; // AWS FIXME - add reset return 0; } int AwsXcl::xclReClock2(unsigned short region, const unsigned short *targetFreqMHz) { #ifdef INTERNAL_TESTING awsmgmt_ioc_freqscaling obj = {0, targetFreqMHz[0], targetFreqMHz[1], targetFreqMHz[2], 0}; return ioctl(mMgtHandle, AWSMGMT_IOCFREQSCALING, &obj); #else // # error "INTERNAL_TESTING macro disabled. AMZN code goes here. " // # This API is not supported in AWS, the frequencies are set per AFI return 0; #endif } ssize_t AwsXcl::xclUnmgdPwrite(unsigned flags, const void *buf, size_t count, uint64_t offset) { if (flags) return -EINVAL; drm_xocl_pwrite_unmgd unmgd = {0, 0, offset, count, reinterpret_cast<uint64_t>(buf)}; return ioctl(mUserHandle, DRM_IOCTL_XOCL_PWRITE_UNMGD, &unmgd); } ssize_t AwsXcl::xclUnmgdPread(unsigned flags, void *buf, size_t count, uint64_t offset) { if (flags) return -EINVAL; drm_xocl_pread_unmgd unmgd = {0, 0, offset, count, reinterpret_cast<uint64_t>(buf)}; return ioctl(mUserHandle, DRM_IOCTL_XOCL_PREAD_UNMGD, &unmgd); } int AwsXcl::xclExportBO(unsigned int boHandle) { drm_prime_handle info = {boHandle, 0, -1}; int result = ioctl(mUserHandle, DRM_IOCTL_PRIME_HANDLE_TO_FD, &info); return !result ? info.fd : result; } unsigned int AwsXcl::xclImportBO(int fd, unsigned flags) { /*Sarab drm_xocl_userptr_bo user = {reinterpret_cast<uint64_t>(userptr), size, mNullBO, flags}; int result = ioctl(mUserHandle, DRM_IOCTL_XOCL_USERPTR_BO, &user); */ drm_prime_handle info = {mNullBO, flags, fd}; int result = ioctl(mUserHandle, DRM_IOCTL_PRIME_FD_TO_HANDLE, &info); if (result) { std::cout << __func__ << " ERROR: FD to handle IOCTL failed" << std::endl; } return !result ? info.handle : mNullBO; } int AwsXcl::xclGetBOProperties(unsigned int boHandle, xclBOProperties *properties) { drm_xocl_info_bo info = {boHandle, 0, 0, 0}; int result = ioctl(mUserHandle, DRM_IOCTL_XOCL_INFO_BO, &info); properties->handle = info.handle; properties->flags = info.flags; properties->size = info.size; properties->paddr = info.paddr; properties->domain = XCL_BO_DEVICE_RAM; // currently all BO domains are XCL_BO_DEVICE_RAM return result ? mNullBO : 0; } bool AwsXcl::xclUnlockDevice() { flock(mUserHandle, LOCK_UN); mLocked = false; return true; } // Assume that the memory is always // created for the device ddr for now. Ignoring the flags as well. unsigned int AwsXcl::xclAllocBO(size_t size, xclBOKind domain, unsigned flags) { drm_xocl_create_bo info = {size, mNullBO, flags}; int result = ioctl(mUserHandle, DRM_IOCTL_XOCL_CREATE_BO, &info); if (result) { std::cout << __func__ << " ERROR: AllocBO IOCTL failed" << std::endl; } return result ? mNullBO : info.handle; } unsigned int AwsXcl::xclAllocUserPtrBO(void *userptr, size_t size, unsigned flags) { drm_xocl_userptr_bo user = {reinterpret_cast<uint64_t>(userptr), size, mNullBO, flags}; int result = ioctl(mUserHandle, DRM_IOCTL_XOCL_USERPTR_BO, &user); return result ? mNullBO : user.handle; } void AwsXcl::xclFreeBO(unsigned int boHandle) { drm_gem_close closeInfo = {boHandle, 0}; ioctl(mUserHandle, DRM_IOCTL_GEM_CLOSE, &closeInfo); } int AwsXcl::xclWriteBO(unsigned int boHandle, const void *src, size_t size, size_t seek) { drm_xocl_pwrite_bo pwriteInfo = { boHandle, 0, seek, size, reinterpret_cast<uint64_t>(src) }; return ioctl(mUserHandle, DRM_IOCTL_XOCL_PWRITE_BO, &pwriteInfo); } int AwsXcl::xclReadBO(unsigned int boHandle, void *dst, size_t size, size_t skip) { drm_xocl_pread_bo preadInfo = { boHandle, 0, skip, size, reinterpret_cast<uint64_t>(dst) }; return ioctl(mUserHandle, DRM_IOCTL_XOCL_PREAD_BO, &preadInfo); } void *AwsXcl::xclMapBO(unsigned int boHandle, bool write) { drm_xocl_info_bo info = { boHandle, 0, 0 }; int result = ioctl(mUserHandle, DRM_IOCTL_XOCL_INFO_BO, &info); if (result) return nullptr; drm_xocl_map_bo mapInfo = { boHandle, 0, 0 }; result = ioctl(mUserHandle, DRM_IOCTL_XOCL_MAP_BO, &mapInfo); if (result) return nullptr; return mmap(0, info.size, (write ? (PROT_READ|PROT_WRITE) : PROT_READ), MAP_SHARED, mUserHandle, mapInfo.offset); } int AwsXcl::xclSyncBO(unsigned int boHandle, xclBOSyncDirection dir, size_t size, size_t offset) { drm_xocl_sync_bo_dir drm_dir = (dir == XCL_BO_SYNC_BO_TO_DEVICE) ? DRM_XOCL_SYNC_BO_TO_DEVICE : DRM_XOCL_SYNC_BO_FROM_DEVICE; drm_xocl_sync_bo syncInfo = {boHandle, 0, size, offset, drm_dir}; return ioctl(mUserHandle, DRM_IOCTL_XOCL_SYNC_BO, &syncInfo); } #ifndef INTERNAL_TESTING int AwsXcl::loadDefaultAfiIfCleared( void ) { int array_len = 16; fpga_slot_spec spec_array[ array_len ]; std::memset( spec_array, mBoardNumber, sizeof(fpga_slot_spec) * array_len ); fpga_pci_get_all_slot_specs( spec_array, array_len ); if( spec_array[mBoardNumber].map[FPGA_APP_PF].device_id == AWS_UserPF_DEVICE_ID ) { std::string agfi = DEFAULT_GLOBAL_AFI; fpga_mgmt_load_local_image( mBoardNumber, const_cast<char*>(agfi.c_str()) ); if( sleepUntilLoaded( agfi ) ) { std::cout << "ERROR: Sleep until load failed." << std::endl; return -1; } fpga_pci_rescan_slot_app_pfs( mBoardNumber ); } return 0; } int AwsXcl::sleepUntilLoaded( const std::string afi ) { fpga_mgmt_image_info info; int max_retries = 20; int seconds_to_wait = 5; for( int i = 0; i < max_retries; i++ ) { // Wait for 10 seconds before checking status std::this_thread::sleep_for( std::chrono::seconds( seconds_to_wait ) ); std::memset( &info, 0, sizeof(struct fpga_mgmt_image_info) ); // Get describe result in the info object int result = fpga_mgmt_describe_local_image( mBoardNumber, &info, 0 ); if( result ) { std::cout << "ERROR: Load image failed." << std::endl; return 1; } if( (info.status == FPGA_STATUS_LOADED) && !std::strcmp(info.ids.afi_id, const_cast<char*>(afi.c_str())) ) { break; } // Increment wait time seconds_to_wait++; } // If after the timeout we check once more if our status is LOADED if( info.status != FPGA_STATUS_LOADED ) { std::cout << "ERROR: Load image failed after waiting till timeout." << std::endl; return 1; } // After the AFI is loaded, we check again if the AFI ID is the correct one if( std::strcmp(info.ids.afi_id, const_cast<char*>(afi.c_str())) ) { std::cout << "ERROR: AFI loaded is not the one we are waiting on." << std::endl; return 1; } // If we have reached here, things look good return 0; } int AwsXcl::checkAndSkipReload( char *afi_id, fpga_mgmt_image_info *orig_info ) { if( (orig_info->status == FPGA_STATUS_LOADED) && !std::strcmp(orig_info->ids.afi_id, afi_id) ) { std::cout << "This AFI already loaded. Skip reload!" << std::endl; int result = 0; //existing afi matched. uint16_t status = 0; result = fpga_mgmt_get_vDIP_status(mBoardNumber, &status); if(result) { printf("Error: can not get virtual DIP Switch state\n"); return result; } //Set bit 0 to 1 status |= (1 << 0); result = fpga_mgmt_set_vDIP(mBoardNumber, status); if(result) { printf("Error trying to set virtual DIP Switch \n"); return result; } std::this_thread::sleep_for(std::chrono::microseconds(250)); //pulse the changes in. result = fpga_mgmt_get_vDIP_status(mBoardNumber, &status); if(result) { printf("Error: can not get virtual DIP Switch state\n"); return result; } //Set bit 0 to 0 status &= ~(1 << 0); result = fpga_mgmt_set_vDIP(mBoardNumber, status); if(result) { printf("Error trying to set virtual DIP Switch \n"); return result; } std::this_thread::sleep_for(std::chrono::microseconds(250)); printf("Successfully skipped reloading of local image.\n"); return result; } else { std::cout << "AFI not yet loaded, proceed to download." << std::endl; return 1; } } #endif } /* end namespace awsbmhal */ xclDeviceHandle xclOpen(unsigned deviceIndex, const char *logFileName, xclVerbosityLevel level) { if(xcldev::pci_device_scanner::device_list.size() <= deviceIndex) { printf("Cannot find index %d \n", deviceIndex); return nullptr; } awsbwhal::AwsXcl *handle = new awsbwhal::AwsXcl(deviceIndex, logFileName, level); if (!awsbwhal::AwsXcl::handleCheck(handle)) { printf("WARNING: xclOpen Handle check failed\n"); delete handle; handle = nullptr; #ifndef INTERNAL_TESTING /* workaround necessary to load a default afi and program with xclbin when device is in a cleared state */ xcldev::pci_device_scanner rescan; rescan.clear_device_list(); rescan.scan( true ); for (unsigned int i=0; i<rescan.device_list.size(); i++) { std::cout << "device[" << i << "].user_instance : " << rescan.device_list[ i ].user_instance << std::endl; if (rescan.device_list[i].user_instance == 128) { deviceIndex = i; break; } } handle = new awsbwhal::AwsXcl(deviceIndex, logFileName, level); if (!awsbwhal::AwsXcl::handleCheck(handle)) { printf("ERROR: xclOpen Handle check failed\n"); delete handle; handle = nullptr; } #endif } return static_cast<xclDeviceHandle>(handle); } void xclClose(xclDeviceHandle handle) { awsbwhal::AwsXcl *drv = awsbwhal::AwsXcl::handleCheck(handle); if (drv) delete drv; } int xclGetDeviceInfo2(xclDeviceHandle handle, xclDeviceInfo2 *info) { awsbwhal::AwsXcl *drv = awsbwhal::AwsXcl::handleCheck(handle); if (!drv) return -1; return drv->xclGetDeviceInfo2(info); } int xclLoadBitstream(xclDeviceHandle handle, const char *xclBinFileName) { return -ENOSYS; } int xclLoadXclBin(xclDeviceHandle handle, const xclBin *buffer) { awsbwhal::AwsXcl *drv = awsbwhal::AwsXcl::handleCheck(handle); if (!drv) return -1; return drv->xclLoadXclBin(buffer); } size_t xclWrite(xclDeviceHandle handle, xclAddressSpace space, uint64_t offset, const void *hostBuf, size_t size) { awsbwhal::AwsXcl *drv = awsbwhal::AwsXcl::handleCheck(handle); if (!drv) return -1; return drv->xclWrite(space, offset, hostBuf, size); } size_t xclRead(xclDeviceHandle handle, xclAddressSpace space, uint64_t offset, void *hostBuf, size_t size) { awsbwhal::AwsXcl *drv = awsbwhal::AwsXcl::handleCheck(handle); if (!drv) return -1; return drv->xclRead(space, offset, hostBuf, size); } uint64_t xclAllocDeviceBuffer(xclDeviceHandle handle, size_t size) { awsbwhal::AwsXcl *drv = awsbwhal::AwsXcl::handleCheck(handle); if (!drv) return -1; return drv->xclAllocDeviceBuffer(size); } uint64_t xclAllocDeviceBuffer2(xclDeviceHandle handle, size_t size, xclMemoryDomains domain, unsigned flags) { awsbwhal::AwsXcl *drv = awsbwhal::AwsXcl::handleCheck(handle); if (!drv) return -1; return drv->xclAllocDeviceBuffer2(size, domain, flags); } void xclFreeDeviceBuffer(xclDeviceHandle handle, uint64_t buf) { awsbwhal::AwsXcl *drv = awsbwhal::AwsXcl::handleCheck(handle); if (!drv) return; return drv->xclFreeDeviceBuffer(buf); } size_t xclCopyBufferHost2Device(xclDeviceHandle handle, uint64_t dest, const void *src, size_t size, size_t seek) { awsbwhal::AwsXcl *drv = awsbwhal::AwsXcl::handleCheck(handle); if (!drv) return -1; return drv->xclCopyBufferHost2Device(dest, src, size, seek); } size_t xclCopyBufferDevice2Host(xclDeviceHandle handle, void *dest, uint64_t src, size_t size, size_t skip) { awsbwhal::AwsXcl *drv = awsbwhal::AwsXcl::handleCheck(handle); if (!drv) return -1; return drv->xclCopyBufferDevice2Host(dest, src, size, skip); } //This will be deprecated. int xclUpgradeFirmware(xclDeviceHandle handle, const char *fileName) { awsbwhal::AwsXcl *drv = awsbwhal::AwsXcl::handleCheck(handle); if (!drv) return -1; return xclUpgradeFirmware2(handle, fileName, 0); } int xclUpgradeFirmware2(xclDeviceHandle handle, const char *fileName1, const char* fileName2) { awsbwhal::AwsXcl *drv = awsbwhal::AwsXcl::handleCheck(handle); if (!drv) return -1; return -ENOSYS; } /* * xclBootFPGA * * Sequence: * 1) call boot ioctl * 2) close the device, unload the driver * 3) remove and scan * 4) rescan pci devices * 5) reload the driver (done by the calling function xcldev::boot()) * * Return 0 on success, -1 on failure. */ int xclBootFPGA(xclDeviceHandle handle) { // awsbwhal::AwsXcl *drv = awsbwhal::AwsXcl::handleCheck(handle); // if (!drv) // return -1; // return -ENOSYS; int retVal = -1; //awsbwhal::AwsXcl *drv = awsbwhal::AwsXcl::handleCheck(handle); // retVal = drv->xclBootFPGA(); // boot ioctl retVal = 0; // skip boot ioctl since this may not be possible for AWS if( retVal == 0 ) { xclClose(handle); // close the device, unload the driver retVal = xclRemoveAndScanFPGA(); // remove and scan } if( retVal == 0 ) { xcldev::pci_device_scanner devScanner; devScanner.scan( true ); // rescan pci devices } return retVal; } int xclRemoveAndScanFPGA( void ) { const std::string devPath = "/devices/"; const std::string removePath = "/remove"; const std::string pciPath = "/sys/bus/pci"; const std::string rescanPath = "/rescan"; const char *input = "1\n"; // remove devices "echo 1 > /sys/bus/pci/devices/<deviceHandle>/remove" for (unsigned int i = 0; i < xcldev::pci_device_scanner::device_list.size(); i++) { std::string dev_name_pf_user = pciPath + devPath + xcldev::pci_device_scanner::device_list[i].user_name + removePath; std::string dev_name_pf_mgmt = pciPath + devPath + xcldev::pci_device_scanner::device_list[i].mgmt_name + removePath; std::ofstream userFile( dev_name_pf_user ); if( !userFile.is_open() ) { perror( dev_name_pf_user.c_str() ); return errno; } userFile << input; std::ofstream mgmtFile( dev_name_pf_mgmt ); if( !mgmtFile.is_open() ) { perror( dev_name_pf_mgmt.c_str() ); return errno; } mgmtFile << input; } std::this_thread::sleep_for(std::chrono::seconds(1)); // initiate rescan "echo 1 > /sys/bus/pci/rescan" std::ofstream rescanFile( pciPath + rescanPath ); if( !rescanFile.is_open() ) { perror( std::string( pciPath + rescanPath ).c_str() ); return errno; } rescanFile << input; return 0; } unsigned xclProbe() { return awsbwhal::AwsXcl::xclProbe(); } int xclResetDevice(xclDeviceHandle handle, xclResetKind kind) { awsbwhal::AwsXcl *drv = awsbwhal::AwsXcl::handleCheck(handle); if (!drv) return -1; return -ENOSYS; } int xclReClock2(xclDeviceHandle handle, unsigned short region, const unsigned short *targetFreqMHz) { awsbwhal::AwsXcl *drv = awsbwhal::AwsXcl::handleCheck(handle); if (!drv) return -1; return drv->xclReClock2(region, targetFreqMHz); } int xclLockDevice(xclDeviceHandle handle) { awsbwhal::AwsXcl *drv = awsbwhal::AwsXcl::handleCheck(handle); if (!drv) return -1; return drv->xclLockDevice() ? 0 : -1; } //Sarab: Added for HAL2 support with XOCL GEM Driver int xclExportBO(xclDeviceHandle handle, unsigned int boHandle) { awsbwhal::AwsXcl *drv = awsbwhal::AwsXcl::handleCheck(handle); return drv ? drv->xclExportBO(boHandle) : -ENODEV; } unsigned int xclImportBO(xclDeviceHandle handle, int fd, unsigned flags) { awsbwhal::AwsXcl *drv = awsbwhal::AwsXcl::handleCheck(handle); if (!drv) { std::cout << __func__ << ", " << std::this_thread::get_id() << ", handle & XOCL Device are bad" << std::endl; } return drv ? drv->xclImportBO(fd, flags) : -ENODEV; } ssize_t xclUnmgdPwrite(xclDeviceHandle handle, unsigned flags, const void *buf, size_t count, uint64_t offset) { awsbwhal::AwsXcl *drv = awsbwhal::AwsXcl::handleCheck(handle); return drv ? drv->xclUnmgdPwrite(flags, buf, count, offset) : -ENODEV; } int xclGetBOProperties(xclDeviceHandle handle, unsigned int boHandle, xclBOProperties *properties) { awsbwhal::AwsXcl *drv = awsbwhal::AwsXcl::handleCheck(handle); return drv ? drv->xclGetBOProperties(boHandle, properties) : -ENODEV; } ssize_t xclUnmgdPread(xclDeviceHandle handle, unsigned flags, void *buf, size_t count, uint64_t offset) { awsbwhal::AwsXcl *drv = awsbwhal::AwsXcl::handleCheck(handle); return drv ? drv->xclUnmgdPread(flags, buf, count, offset) : -ENODEV; } int xclUpgradeFirmwareXSpi(xclDeviceHandle handle, const char *fileName, int index) { awsbwhal::AwsXcl *drv = awsbwhal::AwsXcl::handleCheck(handle); if (!drv) return -1; return -ENOSYS; //return drv->xclUpgradeFirmwareXSpi(fileName, index); Not supported by AWS } int xclUnlockDevice(xclDeviceHandle handle) { awsbwhal::AwsXcl *drv = awsbwhal::AwsXcl::handleCheck(handle); if (!drv) { std::cout << "xclUnlockDevice returning -ENODEV\n"; return -ENODEV; } else { return drv->xclUnlockDevice() ? 0 : 1; } } unsigned int xclAllocBO(xclDeviceHandle handle, size_t size, xclBOKind domain, unsigned flags) { awsbwhal::AwsXcl *drv = awsbwhal::AwsXcl::handleCheck(handle); return drv ? drv->xclAllocBO(size, domain, flags) : -ENODEV; } unsigned int xclAllocUserPtrBO(xclDeviceHandle handle, void *userptr, size_t size, unsigned flags) { awsbwhal::AwsXcl *drv = awsbwhal::AwsXcl::handleCheck(handle); return drv ? drv->xclAllocUserPtrBO(userptr, size, flags) : -ENODEV; } void xclFreeBO(xclDeviceHandle handle, unsigned int boHandle) { awsbwhal::AwsXcl *drv = awsbwhal::AwsXcl::handleCheck(handle); if (!drv) return; drv->xclFreeBO(boHandle); } size_t xclWriteBO(xclDeviceHandle handle, unsigned int boHandle, const void *src, size_t size, size_t seek) { awsbwhal::AwsXcl *drv = awsbwhal::AwsXcl::handleCheck(handle); return drv ? drv->xclWriteBO(boHandle, src, size, seek) : -ENODEV; } size_t xclReadBO(xclDeviceHandle handle, unsigned int boHandle, void *dst, size_t size, size_t skip) { awsbwhal::AwsXcl *drv = awsbwhal::AwsXcl::handleCheck(handle); return drv ? drv->xclReadBO(boHandle, dst, size, skip) : -ENODEV; } void *xclMapBO(xclDeviceHandle handle, unsigned int boHandle, bool write) { awsbwhal::AwsXcl *drv = awsbwhal::AwsXcl::handleCheck(handle); return drv ? drv->xclMapBO(boHandle, write) : nullptr; } int xclSyncBO(xclDeviceHandle handle, unsigned int boHandle, xclBOSyncDirection dir, size_t size, size_t offset) { awsbwhal::AwsXcl *drv = awsbwhal::AwsXcl::handleCheck(handle); return drv ? drv->xclSyncBO(boHandle, dir, size, offset) : -ENODEV; } unsigned int xclVersion () { return 2; } int xclGetErrorStatus(xclDeviceHandle handle, xclErrorStatus *info) { awsbwhal::AwsXcl *drv = awsbwhal::AwsXcl::handleCheck(handle); if (!drv) return -1; return -ENOSYS; //return drv->xclGetErrorStatus(info); Not supported for AWS } int xclXbsak(int argc, char *argv[]) { return xcldev::xclXbsak(argc, argv); }