Defining Blocks Using Function Templates - 2025.2 English - UG1483

Vitis Model Composer User Guide (UG1483)

Document ID
UG1483
Release Date
2025-11-20
Version
2025.2 English
Important: To use template syntax, specify your function signature and definition in a header file when running xmcImportFunction.

It is common to write functions that accept only predetermined data types, such as int32. However, you might need to create a block that accepts inputs of different sizes, or supports different data types. You might also want to create a block that accepts signals with different fixed-point lengths and fractional lengths. For these scenarios, you can use a function template. These let you create a block that accepts a variable signal size, data type, or data dimensions.

You can define blocks using function templates, as shown in the following example:

#include <stdint.h>
template <int ROWS, int COLS>
void simple_matrix_add(const int16_t in1[ROWS][COLS],
                       const int16_t in2[ROWS][COLS],
                       int16_t out[ROWS][COLS]) {
   for (int i = 0; i<ROWS; i++) { 
      for (int j = 0; j<COLS; j++) { 
         out[i][j] = in1[i][j] + in2[i][j]; 
      }   
   } 
}

The example uses the template parameters ROWS and COLS. The actual dimensions of the input and output arrays, in1[ROWS][COLS] for instance, are determined at simulation time by the dimensions of the input signals to the block. ROWS and COLS are template parameters. These define the dimensions of the function arguments, and are also used in the body of the function, i<ROWS for example.

Use the command below to import the function into Model Composer:
xmcImportFunction('SimpleLib',{'simple_matrix_add'},...
'template_example.h',{},{},'unlock')
Tip: In the example above the ellipsis (...) indicates a continuation of the command on the next line. Refer to Continue Long Statements on Multiple Lines in the MATLAB documentation for more information.

You can perform simple arithmetic operations using template parameters. For example, the following code multiplies the ROWS and COLS of the input matrix to define the output, as shown in the following figure.

#include <stdint.h>
#pragma XMC INPORT in
#pragma XMC OUTPORT out
template<int ROWS,int COLS>
void columnize(const int16_t in[ROWS][COLS], int16_t out[ROWS*COLS]) {
   for (int i = 0; i<ROWS; i++) {
      for (int j = 0; j<COLS; j++) { 
         out[i*COLS+j] = in[i][j];
      }
   }
}
Figure 1. Columnize Function

Other simple supported operations include +, -, *, /, %, <<, and >>, using both the template parameters and integer constants. For example:

template<int M, int N>
void func(const int in[M][N], int out[M*2][M*N]);

template<int ROWS, int COLS>
void func(array[2 * (ROWS + 1) + COLS + 3]);

You can also define a function template that uses a fixed-point data type of variable word length and integer length using function templates. The following example shows this:

#include <stdint.h>
#include <ap_fixed.h>
#pragma XMC OUTPORT out
template <int WordLen, int IntLen>
void fixed_add(const ap_fixed<WordLen,IntLen> in1, 
                      const ap_fixed<WordLen,IntLen> in2, 
                      ap_fixed<WordLen+1,IntLen> &out) {
   out = in1+in2;
}

The example above uses the fixed point notations from Vitis HLS, which specifies the word length and the integer length. In Model Composer, as described in Working with Data Types, you specify the word length and the fractional length. This requires you to use some care in connecting fixed point data types in Model Composer to the imported fixed_add block. For example, in the function above. If WordLen is 16 and IntLen is 11, in Model Composer fixed point data type the word length is 16, and the fractional length is 5.

For more information on fixed-point notation in Vitis HLS, refer to the Vitis High-Level Synthesis User Guide (UG1399).
Tip: As shown in the example above, simple arithmetic operations are also supported in the fixed point template parameter.
To import the fixed_add function and create a block in Model Composer, use the following command:
xmcImportFunction('SimpleLib',{'fixed_add'},fixed_example.h',{},...
{'$XILINX_VIVADO/include'})