# Mapping a Guided Image Filter on the HARP Reconfigurable Architecture Using OpenCL
## 3 OpenCL on HARPv2
### OpenCL Kernel Programming  
The main tasks of an OpenCL host are providing data and invoking the OpenCL kernel. This, however, requires certain API-calls to be made. Some examples are requesting access to the accelerator platform, creating the OpenCL kernel or creating a command queue through which kernel commands can be sent. Therefore, calling a kernel is not as straightforward as just calling a function in C. Altera, now Intel FPGA, adopted the framework by developing a Software Development Kit (SDK) for its FPGA platforms. This SDK is called Intel FPGA SDK for OpenCL, and is built on top of the Intel Quartus software. Intel Quartus is the software package that enables FPGA development for Intel FPGAs in an HDL [13]. Developing OpenCL applications for a CPU-FPGA heterogeneous computing platform is done by programming the CPU in C/C++ and the FPGA in OpenCL. Both languages are higher level languages, in which the specifics of the underlying hardware are concealed. In order to incorporate the hardware information, a Board Support Package (BSP) is defined. The BSP contains logic information, memory information and I/O controllers to communicate with the CPU. An FPGA bitstream is generated in 2 major steps, as depicted in Figure 3. In a first step, the OpenCL kernel is compiled to HDL code by making use of the Altera OpenCL (AOCL) compiler. The hardware information of the FPGA is incorporated in the generated HDL code by making use of the BSP. In the second step, an FPGA bitstream is generated based on the compiled HDL code. In this step, all necessary implementation details, such as selecting the appropriate FPGA frequency, are determined by the Quartus toolchain. This results in an Altera OpenCL executable (aocx) file that contains the FPGA bitstream. The host code, on the other hand, is compiled using an appropriate C compiler. Figure 3: OpenCL and C programming steps to generate an FPGA configuration bitstream. As indicated in the previous sections, there are two types of OpenCL kernels: single work-item kernels and NDRange kernels. In the Intel FPGA SDK for OpenCL, both types of kernels are implemented completely different. When compiling an NDRange kernel, the FPGA implements a GPU-like architecture in which several threads execute simultaneously. This implementation, however, does not make use of pipeline parallelism. Single work-item kernels, on the other hand, are implemented in a pipelined fashion. The iterations in a pipelined loop execute in lockstep using several \(s\) consecutive stages. Multiple consecutive iterations can be executed each in separate stages. The Initiation Interval (II) is the minimal number of cycles to start successive iterations. This interval is subject to data or control dependencies or lack of resources, e.g., memory ports. The II of a pipelined loop largely determines the performance. The desired value for the II is one. In this case, a new loop iteration can be issued every clock cycle, and the implemented hardware will be used 100% of the time. This leads to the optimal performance. If the II, however, is higher, a lower performance will be obtained. For an II of two, only one loop iteration will be started every two clock cycles. Therefore, each pipeline stage will only be used 50% of the time, and the loop will take two times as much time to finish. An II of three leads to a usage of 33.33% and an execution time that is three times higher, and so forth. A large value of II can have several possible causes. Some examples are I/O delay, a limited number of resources or dependencies in the algorithm. When developing a single work-item OpenCL kernel for FPGA, the purpose should always be to obtain an II of one for implemented loops. Higher values lead to a lower use rate and therefore a lower performance. Three main development phases are distinguished when developing an OpenCL project with the Intel FPGA SDK: the emulation phase, the performance tuning phase and the execution phase. In the emulation phase, the behavior of the kernel is verified by emulating the code on a CPU.