The scalar unit floating-point hardware support includes square root,
inverse square root, inverse, absolute value, minimum, and maximum. It supports other
floating-point operations through emulation. The softfloat library must be linked in for test benches and kernel code using
emulation. For math library functions, the single precision float version must be used
(for example, use expf() instead of exp()).
The AI Engine vector unit provides eight lanes of single-precision floating-point multiplication and accumulation. The unit reuses the vector register files and permute network of the fixed-point data path. Only one fixed-point or floating-point vector instruction per cycle can be performed.
Floating-point MACs have a latency of two-cycles, thus, using two accumulators in a ping-pong manner helps performance by allowing the compiler to schedule a MAC on each clock cycle.
aie::accum<accfloat,8> acc1=aie::zeros<accfloat,8>();
aie::accum<accfloat,8> acc2=aie::zeros<accfloat,8>();
aie::vector<float,8> va,vb;
auto ita=aie::begin_vector<8>(data1);
auto itb=aie::begin_vector<8>(data2);
auto ito=aie::begin(out);
for(int i=0;i<32;i++)
chess_prepare_for_pipelining
{
va=*ita++;
vb=*itb++;
acc1=aie::mac(acc1,va,vb);
va=*ita++;
vb=*itb++;
acc2=aie::mac(acc2,va,vb);
}
auto acc=aie::add(acc1,acc2);
auto sum=aie::reduce_add(acc.to_vector<float>(0));
*ito=(float)sum;
There is a scalar float divide function aie::div, but there is no divide vector function at this time. However,
vector division can be implemented via an inverse and multiply as shown in the following
example.
aie::vector<float,8> vf_div,vf1,vf1_inv,vf2;
vf1_inv=aie::inv(vf1);
vf_div=aie::mul(vf1_inv,vf2);
The following API functions support operations on a scalar or all elements of a vector.
-
aie::inv -
aie::sqrt -
aie::invsqrt -
aie::sin -
aie::cos -
aie::sincos: Same as sin and cos, but performs both operations and returns astd::pairof vectors of result values. The first vector contains the sine values, the second contains the cosine values -
aie::sincos_complex: Same as sincos, but returns both values as the real and imaginary parts of a complex number (cos in the real part, sin in the imaginary part).
For aie::sin, aie::cos, and aie::sincos, the input can
either be a float value in radians or an integer. The floating-point range is [-Pi, Pi].
Integer values are handled as a fixed-point input value in Q1.31 format scaled with 1/Pi
(input value 2^31 corresponds to Pi). In this case, only the upper 20 bits of the input
value are used. According to input type, the returned value is either a float or a
signed Q0.15 fixed-point format.
alignas(aie::vector_decl_align) static int16 dds_stored [16]={...};
aie::vector<cint16,8> dds=aie::load_v<8>((cint16*)dds_stored);
int32 phase_in;
auto [sin_,cos_] = aie::sincos(phase_in << 14) ;
cint16 scvalues={cos_,sin_};
dds.push(scvalues);