This Intel® FPGA tutorial demonstrates how to use the included annotated_class_util.hpp
header file to write cleaner code. You can use this header file to write cleaner code as follows:
- simplify the declaration of annotated types with groups of properties by using the
properties_t
alias. - create annotated pointers more neatly than the standard USM allocation APIs by using the
alloc_annotated
helper function.
Optimized for | Description |
---|---|
OS | Ubuntu* 20.04 RHEL*/CentOS* 8 SUSE* 15 Windows* 10, 11 Windows Server* 2019 |
Hardware | Intel® Agilex® 7, Agilex® 5, Arria® 10, Stratix® 10, and Cyclone® V FPGAs |
Software | Intel® oneAPI DPC++/C++ Compiler |
What you will learn | How to use the provided helper funtion to allocate host/shared memory with properties for your FPGA IP components |
Time to complete | 10 minutes |
Note: Even though the Intel DPC++/C++ oneAPI compiler is enough to compile for emulation, generating reports and generating RTL, there are extra software requirements for the simulation flow and FPGA compiles.
To use the simulator flow, Intel® Quartus® Prime Pro Edition (or Standard Edition when targeting Cyclone® V) and one of the following simulators must be installed and accessible through your PATH:
- Questa*-Intel® FPGA Edition
- Questa*-Intel® FPGA Starter Edition
- ModelSim® SE
When using the hardware compile flow, Intel® Quartus® Prime Pro Edition (or Standard Edition when targeting Cyclone® V) must be installed and accessible through your PATH.
⚠️ Make sure you add the device files associated with the FPGA that you are targeting to your Intel® Quartus® Prime installation.
⚠️ Make sure the GCC (for Linux) or Visual Studio (for Windows) in your system supports C++20 features. This requires GCC 9 or later (for Linux) or Visual Studio 2019 version 16.11 or later (for Windows).
Note: This tutorial does not apply to the FPGA acceleration flow as it demonstrates a SYCL HLS flow specific feature.
This sample is part of the FPGA code samples. It is categorized as a Tier 3 sample that demonstrates an advanced code optimization.
flowchart LR
tier1("Tier 1: Get Started")
tier2("Tier 2: Explore the Fundamentals")
tier3("Tier 3: Explore the Advanced Techniques")
tier4("Tier 4: Explore the Reference Designs")
tier1 --> tier2 --> tier3 --> tier4
style tier1 fill:#0071c1,stroke:#0071c1,stroke-width:1px,color:#fff
style tier2 fill:#0071c1,stroke:#0071c1,stroke-width:1px,color:#fff
style tier3 fill:#f96,stroke:#333,stroke-width:1px,color:#fff
style tier4 fill:#0071c1,stroke:#0071c1,stroke-width:1px,color:#fff
Find more information about how to navigate this part of the code samples in the FPGA top-level README.md. You can also find more information about troubleshooting build errors, links to selected documentation, etc.
The annotated_arg
class can be used to customize Avalon memory-mapped interfaces for FPGA IP components. (To learn more about the annotated_arg
class, refer to the code sample mmhost). This tutorial will further demonstrate how to use the helper code in annotated_class_util.hpp
to clean up your code that uses annotated_arg
. You may add annotated_class_util.hpp
to your designs.
Simplify the Declaration of Annotated Types with Groups of Properties by Using the properties_t
Alias
Most oneAPI code assigns properties to an annotated_arg
type using decltype
. For example,
using ArgProps = decltype(sycl::ext::oneapi::experimental::properties{
sycl::ext::intel::experimental::buffer_location<1>,
sycl::ext::intel::experimental::awidth<32>,
sycl::ext::intel::experimental::dwidth<256>,
sycl::ext::oneapi::experimental::alignment<32>,
sycl::ext::intel::experimental::maxburst<8>,
sycl::ext::intel::experimental::latency<0>});
sycl::ext::oneapi::experimental::annotated_arg<int *, ArgProps> arg_x;
The header file "annotated_class_util.hpp" provides a type alias properties_t
(in fpga_tools
namespace) that lets you simplify your code as follows:
#include "annotated_class_util.hpp"
using ArgProps = fpga_tools::properties_t<
sycl::ext::intel::experimental::buffer_location<1>,
sycl::ext::intel::experimental::awidth<32>,
sycl::ext::intel::experimental::dwidth<256>,
sycl::ext::oneapi::experimental::alignment<32>,
sycl::ext::intel::experimental::maxburst<8>,
sycl::ext::intel::experimental::latency<0>>>;
sycl::ext::oneapi::experimental::annotated_arg<int *, ArgProps> arg_x;
Note: to use the
properties_t
alias, you need to add the compiler flag-std=c++20
to your compilation command.-std=c++20
has been added to theUSER_FLAGS
variable in the CMakeLists.txt file of this tutorial:set(USER_FLAGS ${USER_FLAGS} -std=c++20)
Note: The
properties_t
alias can be used on other annotated classes that specify properties in form ofdecltype(sycl::ext::oneapi::experimental::properties{...})
, such as device_global and pipe, assuming you have included the header file "annotation_class_util.hpp" that appears in this code sample.
Allocate Host/Shared Memory with Properties That Match with Avalon Memory-Mapped Host Interfaces by Using the Helper Function alloc_annotated
While SYCL device code must specify annotated_arg
properties at compile time, the SYCL specification allows host code to specify these properties at run time. If you are designing and testing an IP component, this additional flexibility is of no use to you, so you can use the helper function alloc_annotated()
(defined in the utility header file "annotation_class_util.hpp") to simplify your code, while still ensuring that the properties in your host allocations match the properties you defined in your device code.
In the example, the device code defines a SYCL kernel functor that multiplies a factor of 2 to an input vector as follows:
using annotated_arg_t= sycl::ext::oneapi::experimental::annotated_arg<
int *, fpga_tools::properties_t<
sycl::ext::intel::experimental::buffer_location<0>,
sycl::ext::oneapi::experimental::alignment<256>>>;
struct MyIP {
annotated_arg_t a;
int size;
void operator()() const {
#pragma unroll 8
for (int i = 0; i < size; i++) {
a[i] *= 2;
}
}
};
The type of the kernel argument a
is annotated_arg
specified with properties buffer location
and alignment
. To test the IP component in the FPGA simulation, the SYCL host code is required to provide for the kernel arguments runtime values that match with the buffer location
and alignment
. The helper function alloc_annotated
(in fpga_tools
namespace) provides this functionality with code simplicity, as it takes the annotated_arg
type as the only template parameter and returns an instance of the same annotated_arg
type, as the following code snippet shows
#include "annotated_class_util.hpp"
constexpr int kN = 8;
annotated_arg_t array_a = fpga_tools::alloc_annotated<annotated_arg_t>(kN, q);
// Initialize the host array
...
// Launch the kernel
q.single_task(MyIP{array_a, kN}).wait();
Note: "alloc_annotated" function only takes
annotated_arg
templated with pointer types as the valid template parameter.
Note: When working with the command-line interface (CLI), you should configure the oneAPI toolkits using environment variables. Set up your CLI environment by sourcing the
setvars
script located in the root of your oneAPI installation every time you open a new terminal window. This practice ensures that your compiler, libraries, and tools are ready for development.Linux*:
- For system wide installations:
. /opt/intel/oneapi/setvars.sh
- For private installations:
. ~/intel/oneapi/setvars.sh
- For non-POSIX shells, like csh, use the following command:
bash -c 'source <install-dir>/setvars.sh ; exec csh'
Windows*:
C:\Program Files(x86)\Intel\oneAPI\setvars.bat
- Windows PowerShell*, use the following command:
cmd.exe "/K" '"C:\Program Files (x86)\Intel\oneAPI\setvars.bat" && powershell'
For more information on configuring environment variables, see Use the setvars Script with Linux* or macOS* or Use the setvars Script with Windows*.
Use these commands to run the design, depending on your OS.
This design uses CMake to generate a build script for GNU/make.
-
Change to the sample directory.
-
Configure the build system for the Agilex® 7 device family, which is the default.
mkdir build cd build cmake ..
-
Compile the design with the generated
Makefile
. The following build targets are provided, matching the recommended development flow:Compilation Type Command FPGA Emulator make fpga_emu
Optimization Report make report
FPGA Simulator make fpga_sim
FPGA Hardware nmake fpga
This design uses CMake to generate a build script for nmake
.
-
Change to the sample directory.
-
Configure the build system for the Agilex® 7 device family, which is the default.
mkdir build cd build cmake -G "NMake Makefiles" ..
-
Compile the design with the generated
Makefile
. The following build targets are provided, matching the recommended development flow:Compilation Type Command (Windows) FPGA Emulator nmake fpga_emu
Optimization Report nmake report
FPGA Simulator nmake fpga_sim
FPGA Hardware nmake fpga
-
Run the sample on the FPGA emulator (the kernel executes on the CPU):
./annotated_coding.fpga_emu
-
Run the sample on the FPGA simulator device.
CL_CONTEXT_MPSIM_DEVICE_INTELFPGA=1 ./annotated_coding.fpga_sim
-
Run the sample on the FPGA emulator (the kernel executes on the CPU):
annotated_coding.fpga_emu.exe
-
Run the sample on the FPGA simulator device.
set CL_CONTEXT_MPSIM_DEVICE_INTELFPGA=1 annotated_coding.fpga_sim.exe set CL_CONTEXT_MPSIM_DEVICE_INTELFPGA=
Running on device: Intel(R) FPGA Emulation Device
using aligned_alloc_shared to allocate a block of shared memory
using fpga_tools::alloc_annotated to allocate a block of shared memory
PASSED: all kernel results are correct
Code samples are licensed under the MIT license. See License.txt for details.
Third party program Licenses can be found here: third-party-programs.txt.