Any system calls that manage memory allocation within the system, for example,
malloc()
, alloc()
, and
free()
, are using resources that exist in the memory of
the operating system and are created and released during runtime. To be able to synthesize a
hardware implementation the design must be fully self-contained, specifying all required
resources.
Memory allocation system calls must be removed from the design code before
synthesis. Because dynamic memory operations are used to define the functionality of the design,
they must be transformed into equivalent bounded representations. The following code example
shows how a design using malloc()
can be transformed into a
synthesizable version and highlights two useful coding style techniques:
- The design does not use the
__SYNTHESIS__
macro.The user-defined macro
NO_SYNTH
is used to select between the synthesizable and non-synthesizable versions. This ensures that the same code is simulated in C/C++ and synthesized in Vitis HLS. - The pointers in the original design using
malloc()
do not need to be rewritten to work with fixed sized elements.Fixed sized resources can be created and the existing pointer can simply be made to point to the fixed sized resource. This technique can prevent manual recoding of the existing design.
#include "malloc_removed.h"
#include <stdlib.h>
//#define NO_SYNTH
dout_t malloc_removed(din_t din[N], dsel_t width) {
#ifdef NO_SYNTH
long long *out_accum = malloc (sizeof(long long));
int* array_local = malloc (64 * sizeof(int));
#else
long long _out_accum;
long long *out_accum = &_out_accum;
int _array_local[64];
int* array_local = &_array_local[0];
#endif
int i,j;
LOOP_SHIFT:for (i=0;i<N-1; i++) {
if (i<width)
*(array_local+i)=din[i];
else
*(array_local[i])=din[i]>>2;
}
*out_accum=0;
LOOP_ACCUM:for (j=0;j<N-1; j++) {
*out_accum += *(array_local+j);
}
return *out_accum;
}
Because the coding changes here impact the functionality of the design,
Xilinx does not recommend using the __SYNTHESIS__
macro. Xilinx
recommends performing the following steps:
- Add the user-defined macro
NO_SYNTH
to the code and modify the code. - Enable macro
NO_SYNTH
, execute the C/C++ simulation, and save the results. - Disable the macro
NO_SYNTH
, and execute the C/C++ simulation to verify that the results are identical. - Perform synthesis with the user-defined macro disabled.
This methodology ensures that the updated code is validated with C/C++ simulation and that the identical code is then synthesized. As with restrictions on dynamic memory usage in C/C++, Vitis HLS does not support (for synthesis) C/C++ objects that are dynamically created or destroyed.