Other Class Methods, Operators, and Data Members - 2021.1 English

Vitis High-Level Synthesis User Guide (UG1399)

Document ID
UG1399
Release Date
2021-06-16
Version
2021.1 English

The following sections discuss other class methods, operators, and data members.

Bit-Level Operations

The following methods facilitate common bit-level operations on the value stored in ap_[u]int type variables.

Length

int ap_(u)int::length ()

Returns an integer value providing the total number of bits in the ap_[u]int variable.

Concatenation

ap_concat_ref ap_(u)int::concat (ap_(u)int low)  
ap_concat_ref ap_(u)int::operator , (ap_(u)int high, ap_(u)int low)

Concatenates two ap_[u]int variables, the width of the returned value is the sum of the widths of the operands.

The High and Low arguments are placed in the higher and lower order bits of the result respectively; the concat() method places the argument in the lower order bits.

When using the overloaded comma operator, the parentheses are required. The comma operator version may also appear on the LHS of assignment.

Recommended: To avoid unexpected results, explicitly cast C/C++ native types (including integer literals) to an appropriate ap_[u]int type before concatenating.
ap_uint<10> Rslt;

ap_int<3> Val1 = -3;
ap_int<7> Val2 = 54;

Rslt = (Val2, Val1); // Yields: 0x1B5
Rslt = Val1.concat(Val2); // Yields: 0x2B6
(Val1, Val2) = 0xAB; // Yields: Val1 == 1, Val2 == 43

Bit Selection

ap_bit_ref ap_(u)int::operator [] (int bit)

Selects one bit from an arbitrary precision integer value and returns it.

The returned value is a reference value that can set or clear the corresponding bit in this ap_[u]int.

The bit argument must be an int value. It specifies the index of the bit to select. The least significant bit has index 0. The highest permissible index is one less than the bit-width of this ap_[u]int.

The result type ap_bit_ref represents the reference to one bit of this ap_[u]int instance specified by bit.

Range Selection

ap_range_ref ap_(u)int::range (unsigned Hi, unsigned Lo)
ap_range_ref ap_(u)int::operator () (unsigned Hi, unsigned Lo)

Returns the value represented by the range of bits specified by the arguments.

The Hi argument specifies the most significant bit (MSB) position of the range, and Lo specifies the least significant bit (LSB).

The LSB of the source variable is in position 0. If the Hi argument has a value less than Lo, the bits are returned in reverse order.

ap_uint<4> Rslt;

ap_uint<8> Val1 = 0x5f;
ap_uint<8> Val2 = 0xaa;

Rslt = Val1.range(3, 0); // Yields: 0xF
Val1(3,0) = Val2(3, 0); // Yields: 0x5A
Val1(3,0) = Val2(4, 1); // Yields: 0x55
Rslt = Val1.range(4, 7); // Yields: 0xA; bit-reversed!
Note: The object returned by range select is not an ap_(u)int object and lacks operators, but can be used for assignment. To use the range select result in a chained expression with ap_(u)int methods, add an explicit constructor like below.
ap_uint<32> v = 0x8fff0000;
bool r = ap_uint<16>(v.range(23, 8)).xor_reduce();

AND reduce

bool ap_(u)int::and_reduce ()
  • Applies the AND operation on all bits in this ap_(u)int.
  • Returns the resulting single bit.
  • Equivalent to comparing this value against -1 (all ones) and returning true if it matches, false otherwise.

OR reduce

bool ap_(u)int::or_reduce ()
  • Applies the OR operation on all bits in this ap_(u)int.
  • Returns the resulting single bit.
  • Equivalent to comparing this value against 0 (all zeros) and returning false if it matches, true otherwise.

XOR reduce

bool ap_(u)int::xor_reduce ()
  • Applies the XOR operation on all bits in this ap_int.
  • Returns the resulting single bit.
  • Equivalent to counting the number of 1 bits in this value and returning false if the count is even or true if the count is odd.

NAND reduce

bool ap_(u)int::nand_reduce ()
  • Applies the NAND operation on all bits in this ap_int.
  • Returns the resulting single bit.
  • Equivalent to comparing this value against -1 (all ones) and returning false if it matches, true otherwise.

NOR reduce

bool ap_int::nor_reduce ()
  • Applies the NOR operation on all bits in this ap_int.
  • Returns the resulting single bit.
  • Equivalent to comparing this value against 0 (all zeros) and returning true if it matches, false otherwise.

XNOR reduce

bool ap_(u)int::xnor_reduce ()
  • Applies the XNOR operation on all bits in this ap_(u)int.
  • Returns the resulting single bit.
  • Equivalent to counting the number of 1 bits in this value and returning true if the count is even or false if the count is odd.

Bit Reduction Method Examples

ap_uint<8> Val = 0xaa;

bool t = Val.and_reduce(); // Yields: false
t = Val.or_reduce();       // Yields: true
t = Val.xor_reduce();      // Yields: false
t = Val.nand_reduce();     // Yields: true
t = Val.nor_reduce();      // Yields: false
t = Val.xnor_reduce();     // Yields: true

Bit Reverse

void ap_(u)int::reverse ()

Reverses the contents of ap_[u]int instance:

  • The LSB becomes the MSB.
  • The MSB becomes the LSB.

Reverse Method Example

ap_uint<8> Val = 0x12;

Val.reverse(); // Yields: 0x48

Test Bit Value

bool ap_(u)int::test (unsigned i)

Checks whether specified bit of ap_(u)int instance is 1.

Returns true if Yes, false if No.

Test Method Example

ap_uint<8> Val = 0x12;
bool t = Val.test(5); // Yields: true

Set Bit Value

void ap_(u)int::set (unsigned i, bool v)                              
void ap_(u)int::set_bit (unsigned i, bool v)

Sets the specified bit of the ap_(u)int instance to the value of integer V.

Set Bit (to 1)

void ap_(u)int::set (unsigned i)

Sets the specified bit of the ap_(u)int instance to the value 1 (one).

Clear Bit (to 0)

void ap_(u)int:: clear(unsigned i)

Sets the specified bit of the ap_(u)int instance to the value 0 (zero).

Invert Bit

void ap_(u)int:: invert(unsigned i)

Inverts the bit specified in the function argument of the ap_(u)int instance. The specified bit becomes 0 if its original value is 1 and vice versa.

Example of bit set, clear and invert bit methods:

ap_uint<8> Val = 0x12;
Val.set(0, 1); // Yields: 0x13
Val.set_bit(4, false); // Yields: 0x03
Val.set(7); // Yields: 0x83
Val.clear(1); // Yields: 0x81
Val.invert(4); // Yields: 0x91

Rotate Right

void ap_(u)int:: rrotate(unsigned n)

Rotates the ap_(u)int instance n places to right.

Rotate Left

void ap_(u)int:: lrotate(unsigned n)

Rotates the ap_(u)int instance n places to left.

ap_uint<8> Val = 0x12;

Val.rrotate(3); // Yields: 0x42
Val.lrotate(6); // Yields: 0x90

Bitwise NOT

void ap_(u)int:: b_not()
  • Complements every bit of the ap_(u)int instance.
ap_uint<8> Val = 0x12;

Val.b_not(); // Yields: 0xED

Bitwise NOT Example

Test Sign

bool ap_int:: sign()
  • Checks whether the ap_(u)int instance is negative.
  • Returns true if negative.
  • Returns false if positive.

Explicit Conversion Methods

To C/C++ “(u)int”

int ap_(u)int::to_int ()
unsigned ap_(u)int::to_uint ()
  • Returns native C/C++ (32-bit on most systems) integers with the value contained in the ap_[u]int.
  • Truncation occurs if the value is greater than can be represented by an [unsigned] int.

To C/C++ 64-bit “(u)int”

long long ap_(u)int::to_int64 ()
unsigned long long ap_(u)int::to_uint64 ()
  • Returns native C/C++ 64-bit integers with the value contained in the ap_[u]int.
  • Truncation occurs if the value is greater than can be represented by an [unsigned] int.

To C/C++ “double”

double ap_(u)int::to_double ()
  • Returns a native C/C++ double 64-bit floating point representation of the value contained in the ap_[u]int.
  • If the ap_[u]int is wider than 53 bits (the number of bits in the mantissa of a double), the resulting double may not have the exact value expected.
Recommended: Xilinx recommends that you explicitly call member functions instead of using C-style cast to convert ap_[u]int to other data types.

Sizeof

The standard C++ sizeof() function should not be used with ap_[u]int or other classes or instance of object. The ap_int<> data type is a class and sizeof returns the storage used by that class or instance object. sizeof(ap_int<N>) always returns the number of bytes used. For example:

 sizeof(ap_int<127>)=16
 sizeof(ap_int<128>)=16
 sizeof(ap_int<129>)=24
 sizeof(ap_int<130>)=24

Compile Time Access to Data Type Attributes

The ap_[u]int<> types are provided with a static member that allows the size of the variables to be determined at compile time. The data type is provided with the static const member width, which is automatically assigned the width of the data type:


static const int width = _AP_W;

You can use the width data member to extract the data width of an existing ap_[u]int<> data type to create another ap_[u]int<> data type at compile time. The following example shows how the size of variable Res is defined as 1-bit greater than variables Val1 and Val2:

// Definition of basic data type
#define INPUT_DATA_WIDTH 8
typedef ap_int<INPUT_DATA_WIDTH> data_t;
// Definition of variables 
data_t Val1, Val2;
// Res is automatically sized at compile-time to be 1-bit greater than data type 
data_t
ap_int<data_t::width+1> Res = Val1 + Val2;

This ensures that Vitis HLS correctly models the bit-growth caused by the addition even if you update the value of INPUT_DATA_WIDTH for data_t.