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__
The function is defined in simple.cc.
#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.
In order to import the kernel, the signal size of each output port must be specified. 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>
Different cascade data types are supported for each AI Engine architecture.
<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
) that can be either complex or real.
Consider the following example, where a cascade output stream of one kernel is connected 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 the two kernels can be connected to form a cascade connection
using the cascade stream output of block f_osacc48
and the cascade stream input of block f_isaccc48
.
This is shown in the following figure.