Commit 715f5edf authored by lvs's avatar lvs
Browse files

built host with sdx18_1


Former-commit-id: 5a625be3
parent e40708fb
# Description
Version compiled with Intel `Altera OpenCL Compiler 16.0` (Quartus upgraded and patched) targeting the Arria10 reference board `a10gx`.
Source first:
```zsh
% source init_170.sh
```
# Parallel versions
* [ofdock_datapar_alt](./ofdock_datapar_alt): data-parallel
* [ofdock_taskpar_alt](./ofdock_taskpar_alt): task-parallel
# Definition of include file locations
OPENCL12_INCLUDE:= $(XILINX_SDX)/runtime/include/1_2
# Library directories
SDA_LIB:=$(XILINX_SDX)/lib/lnx64.o
opencl_CXXFLAGS=-I$(OPENCL12_INCLUDE)
ifeq ($(ARCH),POWER)
OPENCL_LIB:=$(XILINX_SDX)/runtime/lib/ppc64le
opencl_LDFLAGS=-L$(OPENCL_LIB) -lxilinxopencl -llmx6.0
else
OPENCL_LIB:=$(XILINX_SDX)/runtime/lib/x86_64
opencl_LDFLAGS=-L$(OPENCL_LIB) -L$(SDA_LIB) -lOpenCL -pthread
endif
/**********
Copyright (c) 2018, Xilinx, Inc.
All rights reserved.
Redistribution and use in source and binary forms, with or without modification,
are permitted provided that the following conditions are met:
1. Redistributions of source code must retain the above copyright notice,
this list of conditions and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimer in the documentation
and/or other materials provided with the distribution.
3. Neither the name of the copyright holder nor the names of its contributors
may be used to endorse or promote products derived from this software
without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
**********/
#include <unistd.h>
#include <limits.h>
#include <sys/stat.h>
#include "xcl2.hpp"
namespace xcl {
std::vector<cl::Device> get_devices(const std::string& vendor_name) {
size_t i;
std::vector<cl::Platform> platforms;
cl::Platform::get(&platforms);
cl::Platform platform;
for (i = 0 ; i < platforms.size(); i++){
platform = platforms[i];
std::string platformName = platform.getInfo<CL_PLATFORM_NAME>();
if (platformName == vendor_name){
std::cout << "Found Platform" << std::endl;
std::cout << "Platform Name: " << platformName.c_str() << std::endl;
break;
}
}
if (i == platforms.size()) {
std::cout << "Error: Failed to find Xilinx platform" << std::endl;
exit(EXIT_FAILURE);
}
//Getting ACCELERATOR Devices and selecting 1st such device
std::vector<cl::Device> devices;
platform.getDevices(CL_DEVICE_TYPE_ACCELERATOR, &devices);
return devices;
}
std::vector<cl::Device> get_xil_devices() {
return get_devices("Xilinx");
}
cl::Program::Binaries import_binary_file(std::string xclbin_file_name)
{
std::cout << "INFO: Importing " << xclbin_file_name << std::endl;
if(access(xclbin_file_name.c_str(), R_OK) != 0) {
printf("ERROR: %s xclbin not available please build\n", xclbin_file_name.c_str());
exit(EXIT_FAILURE);
}
//Loading XCL Bin into char buffer
std::cout << "Loading: '" << xclbin_file_name.c_str() << "'\n";
std::ifstream bin_file(xclbin_file_name.c_str(), std::ifstream::binary);
bin_file.seekg (0, bin_file.end);
unsigned nb = bin_file.tellg();
bin_file.seekg (0, bin_file.beg);
char *buf = new char [nb];
bin_file.read(buf, nb);
cl::Program::Binaries bins;
bins.push_back({buf,nb});
return bins;
}
std::string
find_binary_file(const std::string& _device_name, const std::string& xclbin_name)
{
std::cout << "XCLBIN File Name: " << xclbin_name.c_str() << std::endl;
char *xcl_mode = getenv("XCL_EMULATION_MODE");
char *xcl_target = getenv("XCL_TARGET");
std::string mode;
/* Fall back mode if XCL_EMULATION_MODE is not set is "hw" */
if(xcl_mode == NULL) {
mode = "hw";
} else {
/* if xcl_mode is set then check if it's equal to true*/
if(strcmp(xcl_mode,"true") == 0) {
/* if it's true, then check if xcl_target is set */
if(xcl_target == NULL) {
/* default if emulation but not specified is software emulation */
mode = "sw_emu";
} else {
/* otherwise, it's what ever is specified in XCL_TARGET */
mode = xcl_target;
}
} else {
/* if it's not equal to true then it should be whatever
* XCL_EMULATION_MODE is set to */
mode = xcl_mode;
}
}
char *xcl_bindir = getenv("XCL_BINDIR");
// typical locations of directory containing xclbin files
const char *dirs[] = {
xcl_bindir, // $XCL_BINDIR-specified
"xclbin", // command line build
"..", // gui build + run
".", // gui build, run in build directory
NULL
};
const char **search_dirs = dirs;
if (xcl_bindir == NULL) {
search_dirs++;
}
char *device_name = strdup(_device_name.c_str());
if (device_name == NULL) {
printf("Error: Out of Memory\n");
exit(EXIT_FAILURE);
}
// fix up device name to avoid colons and dots.
// xilinx:xil-accel-rd-ku115:4ddr-xpr:3.2 -> xilinx_xil-accel-rd-ku115_4ddr-xpr_3_2
for (char *c = device_name; *c != 0; c++) {
if (*c == ':' || *c == '.') {
*c = '_';
}
}
char *device_name_versionless = strdup(_device_name.c_str());
if (device_name_versionless == NULL) {
printf("Error: Out of Memory\n");
exit(EXIT_FAILURE);
}
unsigned short colons = 0;
bool colon_exist = false;
for (char *c = device_name_versionless; *c != 0; c++) {
if (*c == ':') {
colons++;
*c = '_';
colon_exist = true;
}
/* Zero out version area */
if (colons == 3) {
*c = '\0';
}
}
// versionless support if colon doesn't exist in device_name
if(!colon_exist) {
int len = strlen(device_name_versionless);
device_name_versionless[len - 4] = '\0';
}
const char *aws_file_patterns[] = {
"%1$s/%2$s.%3$s.%4$s.awsxclbin", // <kernel>.<target>.<device>.awsxclbin
"%1$s/%2$s.%3$s.%5$s.awsxclbin", // <kernel>.<target>.<device_versionless>.awsxclbin
"%1$s/binary_container_1.awsxclbin", // default for gui projects
"%1$s/%2$s.awsxclbin", // <kernel>.awsxclbin
NULL
};
const char *file_patterns[] = {
"%1$s/%2$s.%3$s.%4$s.xclbin", // <kernel>.<target>.<device>.xclbin
"%1$s/%2$s.%3$s.%5$s.xclbin", // <kernel>.<target>.<device_versionless>.xclbin
"%1$s/binary_container_1.xclbin", // default for gui projects
"%1$s/%2$s.xclbin", // <kernel>.xclbin
NULL
};
char xclbin_file_name[PATH_MAX];
memset(xclbin_file_name, 0, PATH_MAX);
ino_t aws_ino = 0; // used to avoid errors if an xclbin found via multiple/repeated paths
for (const char **dir = search_dirs; *dir != NULL; dir++) {
struct stat sb;
if (stat(*dir, &sb) == 0 && S_ISDIR(sb.st_mode)) {
for (const char **pattern = aws_file_patterns; *pattern != NULL; pattern++) {
char file_name[PATH_MAX];
memset(file_name, 0, PATH_MAX);
snprintf(file_name, PATH_MAX, *pattern, *dir, xclbin_name.c_str(), mode.c_str(), device_name, device_name_versionless);
if (stat(file_name, &sb) == 0 && S_ISREG(sb.st_mode)) {
char* bindir = strdup(*dir);
if (bindir == NULL) {
printf("Error: Out of Memory\n");
exit(EXIT_FAILURE);
}
if (*xclbin_file_name && sb.st_ino != aws_ino) {
printf("Error: multiple xclbin files discovered:\n %s\n %s\n", file_name, xclbin_file_name);
exit(EXIT_FAILURE);
}
aws_ino = sb.st_ino;
strncpy(xclbin_file_name, file_name, PATH_MAX);
}
}
}
}
ino_t ino = 0; // used to avoid errors if an xclbin found via multiple/repeated paths
// if no awsxclbin found, check for xclbin
if (*xclbin_file_name == '\0') {
for (const char **dir = search_dirs; *dir != NULL; dir++) {
struct stat sb;
if (stat(*dir, &sb) == 0 && S_ISDIR(sb.st_mode)) {
for (const char **pattern = file_patterns; *pattern != NULL; pattern++) {
char file_name[PATH_MAX];
memset(file_name, 0, PATH_MAX);
snprintf(file_name, PATH_MAX, *pattern, *dir, xclbin_name.c_str(), mode.c_str(), device_name, device_name_versionless);
if (stat(file_name, &sb) == 0 && S_ISREG(sb.st_mode)) {
char* bindir = strdup(*dir);
if (bindir == NULL) {
printf("Error: Out of Memory\n");
exit(EXIT_FAILURE);
}
if (*xclbin_file_name && sb.st_ino != ino) {
printf("Error: multiple xclbin files discovered:\n %s\n %s\n", file_name, xclbin_file_name);
exit(EXIT_FAILURE);
}
ino = sb.st_ino;
strncpy(xclbin_file_name, file_name, PATH_MAX);
}
}
}
}
}
// if no xclbin found, preferred path for error message from xcl_import_binary_file()
if (*xclbin_file_name == '\0') {
snprintf(xclbin_file_name, PATH_MAX, file_patterns[0], *search_dirs, xclbin_name.c_str(), mode.c_str(), device_name);
}
free(device_name);
return (xclbin_file_name);
}
bool is_emulation()
{
bool ret =false;
char *xcl_mode = getenv("XCL_EMULATION_MODE");
if (xcl_mode != NULL){
ret = true;
}
return ret;
}
bool is_hw_emulation()
{
bool ret =false;
char *xcl_mode = getenv("XCL_EMULATION_MODE");
if ((xcl_mode != NULL) && !strcmp(xcl_mode, "hw_emu")){
ret = true;
}
return ret;
}
bool is_xpr_device(const char *device_name) {
const char *output = strstr(device_name,"xpr");
if(output==NULL) {
return false;
}
else {
return true;
}
}
};
/**********
Copyright (c) 2018, Xilinx, Inc.
All rights reserved.
Redistribution and use in source and binary forms, with or without modification,
are permitted provided that the following conditions are met:
1. Redistributions of source code must retain the above copyright notice,
this list of conditions and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimer in the documentation
and/or other materials provided with the distribution.
3. Neither the name of the copyright holder nor the names of its contributors
may be used to endorse or promote products derived from this software
without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
**********/
#pragma once
#define CL_HPP_CL_1_2_DEFAULT_BUILD
#define CL_HPP_TARGET_OPENCL_VERSION 120
#define CL_HPP_MINIMUM_OPENCL_VERSION 120
#define CL_HPP_ENABLE_PROGRAM_CONSTRUCTION_FROM_ARRAY_COMPATIBILITY 1
#include <CL/cl2.hpp>
#include <iostream>
#include <fstream>
// When creating a buffer with user pointer (CL_MEM_USE_HOST_PTR), under the hood
// User ptr is used if and only if it is properly aligned (page aligned). When not
// aligned, runtime has no choice but to create its own host side buffer that backs
// user ptr. This in turn implies that all operations that move data to and from
// device incur an extra memcpy to move data to/from runtime's own host buffer
// from/to user pointer. So it is recommended to use this allocator if user wish to
// Create Buffer/Memory Object with CL_MEM_USE_HOST_PTR to align user buffer to the
// page boundary. It will ensure that user buffer will be used when user create
// Buffer/Mem Object with CL_MEM_USE_HOST_PTR.
template <typename T>
struct aligned_allocator
{
using value_type = T;
T* allocate(std::size_t num)
{
void* ptr = nullptr;
if (posix_memalign(&ptr,4096,num*sizeof(T)))
throw std::bad_alloc();
return reinterpret_cast<T*>(ptr);
}
void deallocate(T* p, std::size_t num)
{
free(p);
}
};
namespace xcl {
std::vector<cl::Device> get_xil_devices();
std::vector<cl::Device> get_devices(const std::string& vendor_name);
/* find_xclbin_file
*
*
* Description:
* Find precompiled program (as commonly created by the Xilinx OpenCL
* flow). Using search path below.
*
* Search Path:
* $XCL_BINDIR/<name>.<target>.<device>.xclbin
* $XCL_BINDIR/<name>.<target>.<device_versionless>.xclbin
* $XCL_BINDIR/binary_container_1.xclbin
* $XCL_BINDIR/<name>.xclbin
* xclbin/<name>.<target>.<device>.xclbin
* xclbin/<name>.<target>.<device_versionless>.xclbin
* xclbin/binary_container_1.xclbin
* xclbin/<name>.xclbin
* ../<name>.<target>.<device>.xclbin
* ../<name>.<target>.<device_versionless>.xclbin
* ../binary_container_1.xclbin
* ../<name>.xclbin
* ./<name>.<target>.<device>.xclbin
* ./<name>.<target>.<device_versionless>.xclbin
* ./binary_container_1.xclbin
* ./<name>.xclbin
*
* Inputs:
* _device_name - Targeted Device name
* xclbin_name - base name of the xclbin to import.
*
* Returns:
* An opencl program Binaries object that was created from xclbin_name file.
*/
std::string find_binary_file(const std::string& _device_name, const std::string& xclbin_name);
cl::Program::Binaries import_binary_file(std::string xclbin_file_name);
bool is_emulation () ;
bool is_hw_emulation () ;
bool is_xpr_device (const char *device_name);
}
xcl2_SRCS:=${COMMON_REPO}/libs/xcl2/xcl2.cpp
xcl2_HDRS:=${COMMON_REPO}/libs/xcl2/xcl2.hpp
xcl2_CXXFLAGS:=-I${COMMON_REPO}/libs/xcl2
# By Default report is set to none, so report will be generated
# 'estimate' for estimate report generation
# 'system' for system report generation
REPORT:=none
PROFILE ?= no
# Default C++ Compiler Flags and xocc compiler flags
CXXFLAGS:=-Wall -O0 -g -std=c++14
CLFLAGS:= --xp "param:compiler.preserveHlsOutput=1" --xp "param:compiler.generateExtraRunData=true" -s
ifneq ($(REPORT),none)
CLFLAGS += --report $(REPORT)
endif
ifeq ($(PROFILE),yes)
CLFLAGS += --profile_kernel data:all:all:all
endif
LDCLFLAGS:=$(CLFLAGS)
ifdef XILINX_SDX
XILINX_SDACCEL=${XILINX_SDX}
endif
ifndef XILINX_SDACCEL
$(error XILINX_SDX variable is not set, please set correctly and rerun)
endif
VIVADO=$(XILINX_VIVADO)/bin/vivado
# Use the Xilinx OpenCL compiler
CLC:=$(XILINX_SDACCEL)/bin/xocc
LDCLC:=$(CLC)
EMCONFIGUTIL := $(XILINX_SDACCEL)/bin/emconfigutil
# By default build for X86, this could also be set to POWER to build for power
ARCH:=X86
DEVICES:= xilinx:kcu1500:dynamic
ifeq ($(ARCH),POWER)
CXX:=$(XILINX_SDACCEL)/gnu/ppc64le/4.9.3/lnx64/bin/powerpc64le-linux-gnu-g++
else
CXX:=$(XILINX_SDACCEL)/bin/xcpp
endif
#if COMMON_REPO is not defined use the default value support existing Designs
COMMON_REPO ?= ../../
# By default build for hardware can be set to
# hw_emu for hardware emulation
# sw_emu for software emulation
# or a collection of all or none of these
TARGETS:=hw
# By default only have one device in the system
NUM_DEVICES:=1
# sanitize_dsa - create a filesystem friendly name from dsa name
# $(1) - name of dsa
COLON=:
PERIOD=.
UNDERSCORE=_
sanitize_dsa = $(strip $(subst $(PERIOD),$(UNDERSCORE),$(subst $(COLON),$(UNDERSCORE),$(1))))
device2dsa = $(if $(filter $(suffix $(1)),.xpfm),$(shell $(COMMON_REPO)/utility/parsexpmf.py $(1) dsa 2>/dev/null),$(1))
device2sandsa = $(call sanitize_dsa,$(call device2dsa,$(1)))
device2dep = $(if $(filter $(suffix $(1)),.xpfm),$(dir $(1))/$(shell $(COMMON_REPO)/utility/parsexpmf.py $(1) hw 2>/dev/null) $(1),)
# check.mk - defines rules for testing
NIMBIX_DSA_xilinx_adm-pcie-ku3_2ddr-xpr = nx1
NIMBIX_DSA_xilinx_adm-pcie-7v3_1ddr = nx2
NIMBIX_DSA_xilinx_xil-accel-rd-ku115_4ddr-xpr = nx3
NIMBIX_DSA_xilinx_xil-accel-rd-vu9p_4ddr-xpr = nx4
dsa2type = $(NIMBIX_DSA_$(call sanitize_dsa,$(1)))
nimbix_RUNNER = $(COMMON_REPO)/utility/nimbix/nimbix-run.py $(NIMBIXFLAGS) --type $(call dsa2type,$(1)) --
sw_emu_RUNNER = XCL_EMULATION_MODE=sw_emu
hw_emu_RUNNER = XCL_EMULATION_MODE=hw_emu
loader = $(call $(1)_RUNNER,$(2))
# mk_check - run a check against the application
# $(1) - base name for the check
# $(1)_EXE - executable to run
# $(1)_ARGS - arguments to use by default for the check
# $(1)_DEVICES - whitelist of devices to run the check
# $(1)_DEPS - extra dependencies of the check
# $(2) - compilation target (i.e. hw, hw_emu, sw_emu)
# $(1)_$(2)_ARGS - specialization of arguments for specific targets
# $(3) - device name (i.e. xilinx:adm-pcie-ku3:1ddr:3.0)
# $(1)_$(3)_ARGS - specialization of arguments for specific devices (has
# priority over targets)
# $(1)_$(2)_$(3)_ARGS - specialization of arguments for specific targets and
# devices
define mk_check
ifneq ($(filter $(2),$(call target_blacklist,$(1))),$(2))
ifneq ($(filter $(3),$(call device_blacklist,$(1))),$(3))
.PHONY: $(1)_$(2)_$(call device2sandsa,$(3))_check
$(1)_$(2)_$(call device2sandsa,$(3))_check: $($(1)_DEPS) $($(1)_EXE) $(foreach xclbin,$($(1)_XCLBINS),$(XCLBIN_DIR)/$(xclbin).$(2).$(call device2sandsa,$(3)).xclbin)
ifneq ($(2),hw)
$(EMCONFIGUTIL) --platform $(3) --nd $(NUM_DEVICES)
endif
ifdef $(1)_$(2)_$(call device2sandsa,$(3))_ARGS
$(call loader,$(2),$(3)) ./$($(1)_EXE) $($(1)_$(2)_$(call device2sandsa,$(3))_ARGS)
else
ifdef $(1)_$(call device2sandsa,$(3))_ARGS
$(call loader,$(2),$(3)) ./$($(1)_EXE) $($(1)_$(call device2sandsa,$(3))_ARGS)
else
ifdef $(1)_$(2)_ARGS
$(call loader,$(2),$(3)) ./$($(1)_EXE) $($(1)_$(2)_ARGS)
else
$(call loader,$(2),$(3)) ./$($(1)_EXE) $($(1)_ARGS)
endif
endif
endif
CHECK_GOALS += $(1)_$(2)_$(call device2sandsa,$(3))_check
endif
endif
endef
$(foreach check,$(CHECKS),$(foreach target,$(TARGETS),$(foreach device,$(DEVICES),$(eval $(call mk_check,$(check),$(target),$(device))))))
ifdef CHECK_GOALS
ECHO:= @echo
#Extended help messages
help::
$(ECHO) " make check TARGETS=<sw_emu/hw_emu/hw>"
$(ECHO) " Command to run application/kernel either in emulation(sw_emu/hw_emu) or on board(hw)."
$(ECHO) ""
endif
.PHONY: check
check: $(CHECK_GOALS)
# rules.mk - defines basic rules for building executables and xclbins
# Defines the prefix for each kernel.
XCLBIN_DIR=xclbin
ECHO:= @echo
.PHONY: help
help::
$(ECHO) "Makefile Usage:"
$(ECHO) " make all TARGETS=<sw_emu/hw_emu/hw>"
$(ECHO) " Command to generate the design for specified Target."
$(ECHO) ""
$(ECHO) " make clean"
$(ECHO) " Command to remove the generated non-hardware files."
$(ECHO) ""
$(ECHO) " make cleanall"
$(ECHO) " Command to remove all the generated files."
$(ECHO) ""
target_blacklist = $(if $($(1)_NTARGETS), $($(1)_NTARGETS),)
device_blacklist = $(if $($(1)_NDEVICES), $($(1)_NDEVICES),)
# mk_exe - build an exe from host code
# CXX - compiler to use
# CXXFLAGS - base compiler flags to use
# LDFLAGS - base linker flags to use
# $(1) - name of exe
# $(1)_SRCS - the source files to compile
# $(1)_HDRS - the header files used by sources
# $(1)_CXXFLAGS - extra flags specific to this exe
# $(1)_LDFLAGS - extra linkder flags
define mk_exe
$(1): $($(1)_SRCS) $($(1)_HDRS)
$(CXX) $(CXXFLAGS) $($(1)_CXXFLAGS) $($(1)_SRCS) -o $$@ $($(1)_LDFLAGS) $(LDFLAGS)
EXE_GOALS+= $(1)
endef
# mk_xo - create an xo from a set of kernel sources
# CLC - kernel compiler to use
# CLFLAGS - flags to pass to the compiler
# $(1) - base name for this kernel
# $(1)_SRCS - set of source kernel
# $(1)_HDRS - set of header kernel
# $(1)_CLFLAGS - set clflags per kernel
# $(1)_NDEVICES - set blacklist for devices