Intel® FPGA SDK for OpenCL™ Standard Edition: Programming Guide

ID 683342
Date 4/22/2019
Public
Document Table of Contents

5.6. Implementing Arbitrary Precision Integers

Use the Intel® FPGA SDK for OpenCL™ arbitrary precision integer extension to define integers with a custom bit-width. You can define integer custom bit-widths up to and including 64 bits.

To use the arbitrary precision integer extension, include the following line in your list of header files in your kernel code:
#include "ihc_apint.h"
When you compile a kernel that includes the ihc_apint.h header file, you must include the -I $INTELFPGAOCLSDKROOT/include/kernel_headers option with the aoc command. For example:
aoc <other command options> -I $INTELFPGAOCLSDKROOT/include/kernel_headers <my_kernel_file>
The header enables the arbitrary precision integers extension, and has macros that define C-style declarations for signed and unsigned arbitrary precision integers as follows:
#define ap_int<d> intd_t
#define ap_uint<d> uintd_t
For example, you can declare a 10-bit signed and unsigned arbitrary precision integers as follows:
int10_t x_signed;
uint10_t x_unsigned;

You can declare arbitrary precision integers with widths up to 64 bits.

To use arbitrary precision integers without using the header files, enable the extension with the following pragma directive:
#pragma OPENCL EXTENSION cl_intel_arbitrary_precision_integers : enable
After the pragma declaration, you can declare your arbitrary precision integers as follows:
ap_int<d> intd_t my_signed_integer
ap_uint<d> uintd_t my_unsigned_integer

If you do operations where the bit width of the result is larger than the bit widths of the arguments, you must explicitly cast one of the arguments to the resulting bit width.

For example, if you had the following operation, the result overflows the declared size of the integer:
int10_t a;
int10_t b;
int20_t res;

res = a * b;

In the example, the compiler attempts to instantiate a multiplier that multiplies two 10-bit integers and put the results into another 10-bit integer. The result is then sign extended or zero extended up to 20-bits.

To prevent the overflow, explicitly cast one of the arguments to the resulting bit width as follows:
res = ((int20_t)a) * b
Remember:

When you compile a program for x86-64 platforms, the bit widths for arbitrary precisions integers are rounded up to either 32 bits or 64 bits. When you compile a kernel for an FPGA platform, the bit widths are not rounded up and the arbitrary precision integers remain at their declared bit width.

As a result, an operation that appears to work correctly in an x86-64 program can overflow and lose precision when you compile that same operation in an FPGA kernel. The additional precision provided by bit-width rounding on x86-64 platforms masks possible overflow and precision-loss problems you might encounter when your compile your FPGA kernel.