Casting and Datatype Conversion - 2024.1 English

AI Engine-ML Kernel and Graph Programming Guide (UG1603)

Document ID
Release Date
2024.1 English

Casting functions (aie::vector_cast<DstT>(const Vec& v) and aie::vector.cast_to<DstT>()) allow value casting between vector types with the same size in bits. Accumulator vector types have the casting function aie::accum.cast_to<DstT>(). Generally, using the smallest data type possible will reduce register spillage and improve performance. For example, if a 32-bit accumulator (acc32) can meet the design requirements then it is preferable to use that instead of a larger 64-bit accumulator (acc64).

aie::vector<int16,8> iv;
aie::vector<cint16,4> cv=iv.cast_to<cint16>();
aie::vector<cint16,4> cv2=aie::vector_cast<cint16>(iv);
aie::accum<cacc64,4> acc=aie::mul(cv,cv2);
aie::accum<acc64,4> acc2=acc.cast_to<acc64>();

Standard C++ casts can be also used. But the recommended ways of reading vectors from a buffer are as follows.

  • Use aie::load_v and increment the scalar pointer by the number of elements in the vector.
  • Using vector iterators.

Additional details about aie::load_v and iterators are covered in the following sections.

int16 coeff_buffer[16];
aie::vector<int32,8> coeff=aie::load_v<8>((int32*)coeff_buffer);//cast to int32 and load
auto it = aie::begin_vector<8>(coeff_buffer);//create vector<int16,8> iterator 
aie::vector<int16,8> vec0=*it++;//read first vector<int16,8>
aie::vector<int16,8> vec1=*it;//read second vector<int16,8>

Hardware support is built-in for floating-point to fixed-point (to_fixed()) and fixed-point to floating-point (to_float()) conversions. For example, the fixed-point square root, inverse square root, and inverse (reciprocal) are implemented with floating-point precision and the to_float() and to_fixed() conversions are used before and after the function.

Note: The AI Engine-ML floating-point is not completely compliant with the IEEE standards. For more information about the exceptions, see the Versal Adaptive SoC AIE-ML Architecture Manual (AM020).

The conversion functions (to_float() and to_fixed()) can convert either a vector or scalar to float or fixed type.

int a=48;
float f1=aie::to_float(a); //f1=48.0
float f2=aie::to_float(a,/*position of input binary point*/2); //f2=12.0

int b1=aie::to_fixed(f1);//b1=48
int b2=aie::to_fixed(f1,/*position of output decimal point*/2);//b2=192
aie::vector<float,32> fv;
aie::vector<int32,32> iv=aie::to_fixed<int32>(fv,/*position of output decimal point*/2);

Data can be moved from vector to accumulator using aie::accum.from_vector() or from accumulator to vector using aie::accum.to_vector<DstT>() with shifting and rounding as shown in the following example.

aie::vector<int16,16> v;
aie::accum<acc32,16> acc; 
acc.from_vector(v, 0);

aie::accum<acc32,16> acc2;
aie::vector<int16,16> v2; 
v2 = acc2.to_vector<int16>(15);
The API supports vector conversions between data types:
  • aie::pack: Return a vector by converting each element into half the number of bits.
  • aie::unpack: Return a vector by converting each element into twice the number of bits.

The following is an example code of data conversion and its example output:

aie::vector<int16,16> data;

aie::vector<int8,16> data_smaller=data.pack();
aie::vector<int16,16> data_larger=data_smaller.unpack();

aie::print(data_smaller,true,"smaller data=");
aie::print(data_larger,true,"larger data=");

//Example output:
//data=0 1 2 -32768 -4 -5 -6 32767 3 4 126 130 -8 -9 -300 0 
//smaller data=0 1 2 0 -4 -5 -6 -1 3 4 126 -126 -8 -9 -44 0 
//larger data=0 1 2 0 -4 -5 -6 -1 3 4 126 -126 -8 -9 -44 0