Description
The FUNCTION_INSTANTIATE pragma is an optimization technique that has the area benefits of maintaining the function hierarchy but provides an additional powerful option: performing targeted local optimizations on specific instances of a function. This can simplify the control logic around the function call and potentially improve latency and throughput.
By default:
- Functions remain as separate hierarchy blocks in the RTL.
- All instances of a function, at the same level of hierarchy, make use of a single RTL implementation (block).
The FUNCTION_INSTANTIATE pragma is used to create a unique RTL implementation for each instance of a function, allowing each instance to be locally optimized according to the function call. This pragma exploits the fact that some inputs to a function can be a constant value when the function is called, and uses this to both simplify the surrounding control structures and produce smaller more optimized function blocks.
Without the FUNCTION_INSTANTIATE pragma, the following code results in a
single RTL implementation of function foo_sub
for all three
instances of the function in foo
. Each instance of function
foo_sub
is implemented in an identical manner. This is
fine for function reuse and reducing the area required for each instance call of a function,
but means that the control logic inside the function must be more complex to account for the
variation in each call of foo_sub
.
char foo_sub(char inval, char incr) {
#pragma HLS function_instantiate variable=incr
return inval + incr;
}
void foo(char inval1, char inval2, char inval3,
char *outval1, char *outval2, char * outval3)
{
*outval1 = foo_sub(inval1, 1);
*outval2 = foo_sub(inval2, 2);
*outval3 = foo_sub(inval3, 3);
}
In the code sample above, the FUNCTION_INSTANTIATE pragma results in three
different implementations of function foo_sub
, each
independently optimized for the incr
argument, reducing the
area and improving the performance of the function. After FUNCTION_INSTANTIATE optimization,
foo_sub
is effectively be transformed into three separate
functions, each optimized for the specified values of incr
.
Syntax
Place the pragma in the C source within the boundaries of the required location.
#pragma HLS function_instantiate variable=<variable>
Where:
-
variable=<variable>
- A required argument that defines the function argument to use as a constant.
Examples
In the following example, the FUNCTION_INSTANTIATE
pragma,
placed in function swInt
, allows each instance of function
swInt
to be independently optimized with respect to the
maxv
function argument.
void swInt(unsigned int *readRefPacked, short *maxr, short *maxc, short *maxv){
#pragma HLS function_instantiate variable=maxv
uint2_t d2bit[MAXCOL];
uint2_t q2bit[MAXROW];
#pragma HLS array partition variable=d2bit,q2bit cyclic factor=FACTOR
intTo2bit<MAXCOL/16>((readRefPacked + MAXROW/16), d2bit);
intTo2bit<MAXROW/16>(readRefPacked, q2bit);
sw(d2bit, q2bit, maxr, maxc, maxv);
}