A static variable in a template function is duplicated for each different value of the template arguments.
Different C++ template values passed to a function creates unique instances of the function for each template value. Vitis HLS synthesizes these copies independently within their own context. This can be beneficial as the tool can provide specific optimizations for each unique instance, producing a straightforward implementation of the function.
template<int NC, int K>
void startK(int* dout) {
static int acc=0;
acc += K;
*dout = acc;
}
void foo(int* dout) {
startK<0,1> (dout);
}
void goo(int* dout) {
startK<1,1> (dout);
}
int main() {
int dout0,dout1;
for (int i=0;i<10;i++) {
foo(&dout0);
goo(&dout1);
cout <<"dout0/1 = "<<dout0<<" / "<<dout1<<endl;
}
return 0;
}
Using Templates for Recursion
Templates can also be used to implement a form of recursion that is not supported in standard C synthesis (Recursive Functions).
The following code example shows a case in which a templatized struct
is used to implement a tail-recursion Fibonacci algorithm.
The key to performing synthesis is that a termination class is used to implement the final
call in the recursion, where a template size of one is used.
//Tail recursive call
template<data_t N> struct fibon_s {
template<typename T>
static T fibon_f(T a, T b) {
return fibon_s<N-1>::fibon_f(b, (a+b));
}
};
// Termination condition
template<> struct fibon_s<1> {
template<typename T>
static T fibon_f(T a, T b) {
return b;
}
};
void cpp_template(data_t a, data_t b, data_t &dout){
dout = fibon_s<FIB_N>::fibon_f(a,b);
}