As explained in Data Accessing Mechanisms, stream-based kernels access data streams in a sample-by-sample fashion. Vitis Model Composer supports the following stream-based input and output data types as interfaces to the AIE Kernel block.
-
input_stream<TYPE> -
output_stream<TYPE>
| <Type> | Complexity | Signedness |
|---|---|---|
| int8 | Real | Signed |
| int16 | Real | Signed |
| int32 | Real | Signed |
| int64 | Real | Signed |
| uint8 | Real | Unsigned |
| uint16 | Real | Unsigned |
| uint32 | Real | Unsigned |
| uint64 | Real | Unsigned |
| cint16 | Complex | Signed |
| cint32 | Complex | Signed |
| float | Real | N/A |
| cfloat | Complex | N/A |
| bfloat16 | Real | N/A |
| accfloat | Real | N/A |
| caccfloat | Complex | N/A |
As an example, to import a simple kernel with a stream-based interface. The
following simple.h header file declares the
simple_comp function with one input stream and
one output stream.
#ifndef __COMPLEX_KERNEL_H__
#define __COMPLEX_KERNEL_H__
#include <adf.h>
void simple_comp(input_stream<cint16> * in, output_stream<cint16> * out);
#endif //__COMPLEX_KERNEL_H__
simple.cc defines the function.
#include "simple.h"
void simple_comp(input_stream<cint16> * in, output_stream<cint16> * out) {
cint16 c1, c2;
for (unsigned i=0; i<NUM_SAMPLES; i++) {
c1 = readincr(in);
c2.real = c1.real+c1.imag;
c2.imag = c1.real-c1.imag;
writeincr(out, c2);
}
}
readincr() and writeincr() APIs.Although the function arguments for buffer-based and stream-based kernels are different, the procedure for importing the stream-based kernel is the same.
After a successful import, the Function tab GUI displays automatically. You can quickly review the function definition and ports as shown in the following figure.
To import the kernel, you must specify the signal size of each output port. The following table provides details on this parameter.
| Parameter Name | Description |
|---|---|
| Signal size | This parameter represents the size of the output signal and must be set to a value greater than or equal to the maximum number of samples that are produced during any invocation of the kernel. |
In the General tab, the Import button changes to Update, enabling further updates of block parameters.
Model Composer also supports cascade stream connections between two AI Engine processors.
An AI Engine kernel can use cascade stream connections as follows:
-
input_cascade<TYPE> -
output_cascade<TYPE>
Each AI Engine architecture supports different cascade data types.
| <Type> | Complexity | Signedness |
|---|---|---|
| int8 | Real | Signed |
| uint8 | Real | Unsigned |
| int16 | Real | Signed |
| cint16 | Complex | Signed |
| int32 | Real | Signed |
| cint32 | Complex | Signed |
| float | Real | N/A |
| cfloat | Complex | N/A |
| acc48 | Real | N/A |
| acc80 | Real | N/A |
| cacc48 | Complex | N/A |
| cacc80 | Complex | N/A |
| accfloat | Real | N/A |
| caccfloat | Complex | N/A |
| <Type> | Complexity | Signedness |
|---|---|---|
| int8 | Real | Signed |
| uint8 | Real | Unsigned |
| int16 | Real | Signed |
| uint16 | Real | Unsigned |
| cint16 | Complex | Signed |
| int32 | Real | Signed |
| uint32 | Real | Unsigned |
| cint32 | Complex | Signed |
| bfloat16 | Real | N/A |
| acc32 | Real | N/A |
| acc64 | Real | N/A |
| cacc64 | Complex | N/A |
| accfloat | Real | N/A |
| caccfloat | Complex | N/A |
In Model Composer, a cascade stream port with an accumulator data type is
represented as a fixed point signal (for example, x_sfix48). This can be either complex or real.
Consider the following example where a cascade output stream of one kernel connects to the cascade input stream of another kernel.
#ifndef __CASCADE_KERNELS_H__
#define __CASCADE_KERNELS_H__
void f_osacc48(input_buffer<int32> &i_hi,
input_buffer<int16> &i_lo,
output_cascade<acc48> *o1);
#endif
f_osacc48 has
two input windows: i_hi and i_lo, and one cascade stream output: o1.After importing this kernel function, the AIE Kernel block is as shown in the following figure.
Consider another kernel function f_isacc48, which has one cascade stream input: i1, and two output windows: o_hi and o_lo.
#ifndef __CASCADE_KERNELS_H__
#define __CASCADE_KERNELS_H__
void f_isacc48(input_cascade<acc48> *i1,
output_buffer<int32> &o_hi,
output_buffer<int16> &o_lo);
#endif
After importing the second kernel function, the AIE Kernel block is as shown in the following figure.
Now you can connect the two kernels to form a cascade connection using:
- The cascade stream output of block
f_osacc48. - The cascade stream input of block
f_isaccc48.
The following figure shows this.