Developer Guide

Contents

Advantages and Limitations of Arbitrary Precision Data Types

Advantages

The arbitrary precision data types have the following advantages over the use of standard C/C++ data types:
  • You can achieve narrower data paths and processing elements for various operations in the circuit.
  • The data types ensure that all operations are carried out in a size guaranteed not to lose any data. However, you can still lose data if you store data in a location where the data type is too narrow in size.

Limitations

AC Data Types
The AC data types have the following limitations:
  • Multipliers are limited to generating 512-bit results.
  • Dividers for
    ac_int
    data types are limited to a maximum of 128-bit unsigned or 127-bit signed.
  • Dividers for
    ac_fixed
    data types are limited to a maximum of 64-bits (unsigned or signed).
  • Creation of
    ac_fixed
    variables larger than 32 bits are supported only with the use of the
    bit_fill
    utility function.
    For example:
    // Creating an ac_fixed with value set to 4294967298, which is larger than 2^32. // Unsupported ac_fixed<64, 64, false> v1 = ac_fixed<64, 64, false>(4294967298); // Supported // 4294967298 is 0b100000000000000000000000000000010 in binary // Express that as two 32-bit numbers and use the bit_fill utility function. const int vec_inp[2] = {0x00000001, 0x00000002}; ac_fixed<64, 64, false> bit_fill_res; bit_fill_res.bit_fill<2>(vec_inp);
  • The
    ac_fixed
    math functions
    are limited to returning results that are less than 64 bits in width.
    Certain math functions (for example,
    sincos_fixed
    or
    sincospi_fixed
    ) return fused values and the result's width is twice the input number's width. For such functions, the input number's width must be less than 32.
  • The AC data types are not supported on the Red Hat Enterprise Linux* (RHEL) 7 operating system for emulation due to a bug in the
    glibc
    version bundled with RHEL 7.
  • When using the
    bit_fill_hex()
    function inside a kernel, pass the input string to the kernel through a
    char
    buffer and not as a
    string
    buffer. In addition, hardware and simulation compile flows do not support using a
    string
    literal or passing the string directly to the function. The following are the supported and unsupported code patterns:
    Supported Patterns
    // Supported Pattern 1: Passing string as a char sycl::buffer to the kernel ac_int<140, false> supported_example1(queue &q) { ac_int<140, false> a; std::string hex_string{"0x177632EE7E265080BD54FF0CE7EF42C12"}; constexpr int N = 36; // size of hex_string buffer<ac_int<140, false>, 1> inp1(&a, 1); buffer<char, 1> inp2(hex_string.c_str(), range<1>(N)); q.submit([&](handler &h) { accessor x(inp1, h, read_write); accessor y(inp2, h, read_only); h.single_task<class D>([=] { x[0].bit_fill_hex(&y[0]); }); }); q.wait(); return a; }
    // Supported Pattern 2: Create a char array with the string literal. ac_int<140, false> supported_example2(queue &q) { ac_int<140, false> a; buffer<ac_int<140, false>, 1> inp1(&a, 1); q.submit([&](handler &h) { accessor x(inp1, h, read_write); h.single_task<class D>([=] { char str[36] = "0x177632EE7E265080BD54FF0CE7EF42C12"; x[0].bit_fill_hex(str); }); }); q.wait(); return a; }
    Unsupported Patterns
    // Unsupported Pattern 1 – Using a string Literal, will result in compilation error ac_int<140, false> unsupported_example1(queue& q) { { ac_int<140, false> a; buffer<ac_int<140, false>, 1> a_buff(&a, 1); q.submit([&](handler &h) { accessor a_acc {a_buff, h, write_only, no_init}; h.single_task<class A>([=]() { a_acc[0].bit_fill_hex("1141e98e8c51b7ac7ad387d7f8ee4f1b9"); }); }); q.wait_and_throw(); return a; } }
    // Unsupported Pattern 2 – Passing the string to the kernel in a string sycl::buffer ac_int<140, false> unsupported_example2(queue& q) { { std::string str{"1141e98e8c51b7ac7ad387d7f8ee4f1b9"}; ac_int<140, false> a; buffer<std::string, 1> str_buff(&str, 1); buffer<ac_int<140, false>, 1> a_buff(&a, 1); q.submit([&](handler &h) { accessor str_acc {str_buff, h, read_only}; accessor a_acc {a_buff, h, write_only, no_init}; h.single_task<class B>([=]() { a_acc[0].bit_fill_hex(str_acc[0].c_str()); }); }); q.wait_and_throw(); return a; } }
hls_float
Data Type
The
hls_float
data type has the following limitations:
  • hls_float
    data type is not currently supported on Windows.
  • While the floating-point optimization of converting into constants is performed for
    float
    and
    double
    data types, it is not performed for the
    hls_float
    data type.
  • A limited set of math functions is supported. For details, see Math Functions Supported by hls_float Data Type.
  • Constant initialization works only with the round-towards-zero (
    RZERO
    ) rounding mode.
  • For emulation, the
    hls_float
    math library is not supported on the Red Hat Enterprise Linux* (RHEL) 7 operating system.
  • The
    hls_float
    math functions
    are limited to returning results that are less than 64 bits in width.
    Certain math functions (for example,
    sincos_fixed
    or
    sincospi_fixed
    ) return fused values and the result's width is twice the input number's width. For such functions, the input number's width must be less than 32.
  • When computing
    A^B
    using
    hls_float
    's
    ihc_pown
    function, if
    B
    is an unsigned type
    T
    of size
    N
    bits and is equal to the maximum unsigned value, redefine
    B
    to be of size
    N+1
    bits. Otherwise, results will be incorrect. For example:
    // Sample Code: hls_float<8, 7> a = 2; ac_int<4, false> b = 15; // max value that this ac_int can hold … = ihc_pown(a , b); // !!! Will produce incorrect result
    // Workaround: hls_float<8, 7> a = 2; ac_int<5, false> b = 15; // Workaround … = ihc_pown(a , b); // Will produce correct result

Product and Performance Information

1

Performance varies by use, configuration and other factors. Learn more at www.Intel.com/PerformanceIndex.