Function templates for data types are functions that can operate with generic
data types. This lets you create library functions that can be adapted to support
multiple data types without needing to replicate the code or block in the Vitis Model Composer HLS block library to support each type. The xmcImportFunction
command in Model Composer will create
generic library blocks which the user of the block can connect to signals of any data
types supported by the block.
The data type (typename
) template parameters
are resolved at simulation runtime, when the code and simulation wrapper are generated.
The parameters are replaced during simulation by the actual data types that are
specified by the signals connecting to the library block. The resolved data types can
only be the types that Model Composer supports as discussed in Working with Data Types.
template <typename T>
T max(T x, T y) {
return (x > y) ? x : y;
}
#include <complex>
template <typename T>
void mult_by_two(std::complex< T > x, std::complex< T > *y)
{
*Out = In1 * 2;
}
typename
(or class
) parameters are propagated from input signals on the block, or are
customization parameters that must be defined by the user at simulation runtime. For example, the following function template specifies the parameter ‘T’ as a customization parameter. Because it is not associated with either input argument, 'x' or 'y', it must be specified by the user when the block is added to the model:
template <typename T>
T min(int x, int y) {
return (x < y) ? x : y;
}
The Block Parameters dialog box for the generated Library Function block has an edit field to enter the template argument as shown in the following figure.
In the template syntax, the data type template parameters for function or class can be specified with other template parameters. The order of specification is not important. For example:
template <typename T1, int ROWS, int COLS, int W, int I>
T1 func(T1 x[ROW][COLS], ap_fixed<W, I> &y) {
...
}
SUPPORTED_TYPES/UNSUPPORTED_TYPES Pragma
typename
)
template parameter (or class
), you can also define
the accepted data types for the variable by using either the SUPPORTED_TYPES
or UNSUPPORTED_TYPES
pragma as part of the function signature. This is shown in the following code
example.
#pragma XMC INPORT x
#pragma XMC INPORT y
#pragma XMC SUPPORTED_TYPES T: int8, int16, int32, double, single, half
template <class T>
T max(T x, T y) {
return (x > y) ? x : y;
}
#pragma XMC UNSUPPORTED_TYPES T: boolean
#pragma XMC INPORT x, y
template <typename T>
T min(T x, T y) {
return (x < y) ? x : y;
}
Model Composer supports an extensive list of data types as discussed in Working with Data Types. To specify which of these data
types the template parameter supports, you can either include the list of supported
types, or the unsupported types. The SUPPORTED_TYPES
and UNSUPPORTED_TYPES
pragmas are simply two opposite views of the same thing:
-
SUPPORTED_TYPES
: Specifies a template parameter name (param
), and the list of data types that are accepted by that parameter. This implies the exclusion of all types not listed.#pragma XMC SUPPORTED_TYPES param: type1, type2, ...
-
UNSUPPORTED_TYPES
: Specifies a template parameter name (param
), and the list of data types that are not accepted by that parameter. This implies the inclusion of all types not listed.#pragma XMC UNSUPPORTED_TYPES param: type1, type2, ...
With the SUPPORTED_TYPES
or UNSUPPORTED_TYPES
pragma in place, Model Composer will
check the type of input signal connected to the block to ensure that the data type
is supported. Without the use of one of these pragmas, the data type template
parameter will accept any of the data types supported by Model Composer.
Function Template Specialization and Overloading
Specialization is supported for function templates in the xmcImportFunction
command. Model Composer will create
the library block for the generic function template, supporting multiple data types,
but the block will also include any specialized functions to be used when connected
to input signals with matching data types. Both the generic function, and any
specialization functions are compiled into the block DLL. For example:
template <typename T>
T min(T x, T y) {
return (x < y) ? x : y;
}
template <>
bool min<bool>(bool x, bool y) {
...
}
In this case, Model Composer will call the specialized boolean form
of the min
function when the block is connected to
boolean signals.
int func(int x);
float func(float x);
You can
also overload a function template as shown
below:template <typename T>
int func(int x, T y);
template <typename T>
float func(float x, T y);