definelicht / hlslib

A collection of extensions for Vitis and Intel FPGA OpenCL to improve developer quality of life.
BSD 3-Clause "New" or "Revised" License
304 stars 56 forks source link
cmake fpga high-level-synthesis hpc intel-fpga intel-fpga-opencl sdaccel vitis vivado-hls xilinx

Do you use hlslib? Please consider citing us, and let us know so we can feature your project in the list of examples.

Quick introduction

hlslib is a collection of C++ headers, CMake files, and examples, aimed at improving the quality of life of HLS developers. The current repertoire primarily supports Vitis and Vitis HLS (formerly SDAccel and Vivado HLS), with some support for Intel FPGA OpenCL. An extended abstract describing the project is available here.

This project is developed at the Scalable Parallel Computing Lab (SPCL) at ETH Zurich (see our github).

How do I install it?

There are a few ways:

How do I use it?

Just #include the header(s) you are interested in, and/or put the CMake files somewhere in your project directory and add their path to your ${CMAKE_MODULE_PATH}. You can see an example here!

Officially supported versions of Vitis currently include 2021.2, 2021.1, 2020.2, 2020.1, and 2019.2. Older versions (including SDx and SDAccel) might work, but should be used at your own discretion.

Feature overview

We have Doxygen! Set the CMake flag HLSLIB_BUILD_DOCUMENTATION=ON to generate the docs.

A brief overview of hlslib features is given below.

CMake integration

For integrating the Xilinx or Intel HLS tools in your project, the FindVitis.cmake and FindIntelFPGAOpenCL.cmake are provided in the cmake subdirectory. The scripts will set all necessary variables required to build both host and device code. It also provides the add_vitis_kernel and add_vitis_program functions, which will produce targets for building hardware emulation, hardware, and high-level synthesis.

Example CMakeLists.txt:

set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} hlslib/cmake)
find_package(Vitis REQUIRED)

add_executable(MyHostExecutable src/MyHostExecutable.cpp)
include_directories(${Vitis_INCLUDE_DIRS})
target_link_libraries(MyHostExecutable ${Vitis_LIBRARIES})

# Will populate the "hw", "hw_emu", and "synthesis" targets
add_vitis_kernel(MyKernel FILES src/MyKernel.cpp)
add_vitis_program(MyKernel xilinx_u250_gen3x16_xdma_3_1_202020_1)

Kernels can then be built with:

make hw

The add_vitis_kernel and add_vitis_program functions takes a number of optional arguments that can be used to configure the hardware targets:

add_vitis_kernel(MyKernel
                 FILES src/MyKernel.cpp src/MyKernelHelper.cpp
                 # All flags below this are optional keywords, and any
                 # combination of them can be specified/not specified.
                 KERNEL MyKernelName  # If different from target name
                 HLS_FLAGS "-DMY_IMPORTANT_DEFINITION -O2"
                 DEPENDS include/MyHeader.h include/OtherDependency.h
                 INCLUDE_DIRS ${CMAKE_CURRENT_SOURCE_DIR}/include hlslib/include
                 PORT_MAPPING "ddr0:DDR[0]" "ddr1:DDR[1]")
add_vitis_kernel(MyOtherKernel
                 FILES src/MyOtherKernel.cpp)
add_vitis_program(MyProgram
                  xilinx_u250_gen3x16_xdma_3_1_202020_1  # Name of Vitis platform
                  # All flags below this are optional keywords, and any
                  # combination of them can be specified/not specified.
                  KERNELS MyKernel       # If KERNELS is not specified, the function checks for a kernel
                          MyOtherKernel  # with the same name as specified for the program
                  # Connect multiple linked kernels using streaming interfaces
                  CONNECTIVITY "MyKernel_1.stream_out:MyOtherKernel_1.stream_in"
                  CLOCK 400  # Target a different clock frequency than the default
                  CONFIG scripts/my_config.cfg  # Given as --config to Vitis
                  SAVE_TEMPS ON  # Forwards --save-temps to Vitis
                  BUILD_FLAGS "-Os --export_script"
                  DEBUGGING ON  # Enables Chipscope debugging on all interfaces
                  PROFILING ON)  # Enables profiling for stalls, data transfers, and execution

DataPack

The hlslib::DataPack class located in hlslib/xilinx/DataPack.h facilitates SIMD-style vectorization, and makes it easy to build wide data paths in your code.

Examples usage:

hlslib::DataPack<float, 4> Foo(hlslib::DataPack<float, 4> &a,
                               hlslib::DataPack<float, 4> &b) {
  #pragma HLS INLINE     
  auto add = a + b; // Vector addition
  add[0] = add[1];  // Indexing for both reads and writes
  return 0.5 * add; // Element-wise multiplication by a scalar
}

Simulation

For kernels with multiple processing elements (PEs) executing in parallel, the hlslib/xilinx/Simulation.h adds some convenient macros to simulate this behavior, by wrapping each PE in a thread executed in parallel, all of which are joined when the program terminates.

Example usage:

HLSLIB_DATAFLOW_INIT();
hlslib::Stream<Data_t> pipes[kStages + 1];
HLSLIB_DATAFLOW_FUNCTION(MemoryToStream, memory_in, pipes[0]);
for (int i = 0; i < kStages; ++i) {
  #pragma HLS UNROLL
  HLSLIB_DATAFLOW_FUNCTION(PE, pipes[i], pipes[i + 1]); // Launches new C++ thread
}
HLSLIB_DATAFLOW_FUNCTION(StreamToMemory, pipes[kStages], memory_out);
HLSLIB_DATAFLOW_FINALIZE(); // In simulation mode, joins threads created as dataflow functions.

When building programs using the simulation features, you must link against a thread library (e.g., pthreads).

Stream

While Vivado HLS provides the hls::stream class, it is somewhat lacking in features, in particular when simulating multiple processing elements. The hlslib::Stream class in hlslib/xilinx/Stream.h compiles to Vivado HLS streams, but provides a richer interface. hlslib streams are:

Example usage:

void Bar(hlslib::Stream<int> &a, hlslib::Stream<int> &b, int N) {
  for (int i = 0; i < N; ++i) {
    #pragma HLS PIPELINE II=1
    auto read = a.Pop(); // Queue-like interface
    b.Push(read + 1);
  }
}

void Foo(hlslib::Stream<int> &in_stream, // Specifying stream depth is optional
         hlslib::Stream<int> &out_stream, int N) {
  #pragma HLS DATAFLOW

  hlslib::Stream<int, 4> foo_pipe; // Implements a FIFO of depth 4

  // Dataflow functions running in parallel
  HLSLIB_DATAFLOW_INIT();
  HLSLIB_DATAFLOW_FUNCTION(Bar, in_stream, foo_pipe, N);
  HLSLIB_DATAFLOW_FUNCTION(Bar, foo_pipe, out_stream, N);
  HLSLIB_DATAFLOW_FINALIZE();
}

OpenCL host code

To greatly reduce the amount of boilerplate code required to create and launch OpenCL kernels, and to handle FPGA-specific configuration required by the vendors, hlslib provides a C++14 convenience interface in hlslib/xilinx/OpenCL.h and hlslib/intel/OpenCL.h for Xilinx and Intel FPGA OpenCL, respectively.

Example usage:

using hlslib::ocl;
Context context;
std::vector<float> input_host(N, 5);   
std::vector<float> output_host(N, 5);
auto input_device = context.MakeBuffer<float, Access::read>(
    MemoryBank::bank0, input_host.cbegin(), input_end.cend());
auto output_device = context.MakeBuffer<float, Access::write>(MemoryBank::bank1, N);
auto program = context.MakeProgram("MyKernel.xclbin");
auto kernel = program.MakeKernel("MyKernel", input_device, output_device, N);
kernel.ExecuteTask();
output_device.CopyToHost(output_host.begin());

Other features

Various other features are provided, including:

Some of these headers depend on others. Please refer to the source code.

Ubuntu packages

On Ubuntu, the following package might need to be installed to run hardware emulation:

sudo apt install libc6-dev-i386

Projects using hlslib

If you use hlslib in your project, please let us know, so we can add you to the list.

Bugs and feature requests

Please use the issue tracker.

Publication

If your project uses hlslib, please consider citing us:

BibTeX:

@article{hlslib,
  title={{hlslib}: Software Engineering for Hardware Design},
  author={de~Fine~Licht, Johannes and Hoefler, Torsten},
  journal={arXiv:1910.04436},
  year={2019}
}

Plain text:

J. de Fine Licht and T. Hoefler, "hlslib: Software Engineering for Hardware Design", arXiv:1910.04436 (2019).

References