Static File-scoped Tables
Kernel functions can use private, read-only data structures that are accessed as file-scoped variables. The compiler allocates a limited amount of static heap space for such data. As an example, consider the following header file (user_parameter.h):
#ifndef USER_PARAMETER_H
#define USER_PARAMETER_H
#include <adf.h>
static int32 lutarray[8] = {1,2,3,4,5,6,0,0} ;
#endif
This header file can be included in the kernel source file
and the look-up table can be accessed inside a kernel function directly. The static
modifier ensures that the array definition is
local to this file. The AI Engine compiler then
allocates this array in static heap space for the processor where this kernel is
used.
#include "user_parameter.h"
void simple_lut(input_window_cint16 * in, output_window_cint16 * out){
v4cint32 tmp;
v4cacc48 acc;
v32cint16 coeffs;
upd_w(coeffs, 0, lutarray);
window_readincr(in, tmp);
acc = mul4(tmp 0, 0x3210, 1, coeffs, 0, 0x0000, 1);
acc = mac4(acc, tmp, 2, 0x3210, 1, coeffs, 2, 0x0000, 1) ;
acc = mac4(acc, tmp, 4, 0x3210, 1, coeffs, 4, 0x0000, 1) ;
window_writeincr(out, srs(acc) ) ;
}
Global Graph-scoped Tables
While the previous example only includes an eight entry look-up table accessed as a global variable, many other algorithms require much larger look-up tables. Because AI Engine local memory is at a premium, it is much more efficient for the AI Engine compiler to manage the look-up table explicitly for specific kernels than to leave a large amount of stack or heap space on every processor. Such tables should not be declared static in the kernel header file.
#ifndef USER_PARAMETER_H
#define USER_PARAMETER_H
#include <adf.h>
int32 lutarray[8] = {1,2,3,4,5,6,0,0} ;
#endif
The kernel source continues to include the header file and
use the table as before. But, now you must declare this table as extern
in the graph class header and use the parameter::array(…)
function to create a parameter
object explicitly in the graph. You also need to attach this parameter object to the
kernel as shown in the following code:
#include <adf.h>
extern int32 lutarray[8];
class simple_lut_graph : public graph {
public:
kernel k;
parameter p;
simple_lut_graph() {
k = kernel::create(simple);
p = parameter::array(lutarray);
connect<>(p,k);
...
}
}
Including this explicit specification of the look-up table in the graph description ensures that the compiler is aware of the requirement to reserve a suitably sized piece of memory for the look-up table when it allocates memory for kernel input and output buffers.
Shared Graph-scoped Tables
Sometimes, the same table definition is used in multiple
kernels. Because the AI Engine architecture is a
distributed address-space architecture, each processor binary image that executes
such a kernel needs to have that table defined in its own local memory. To get the
correct graph linkage spread across multiple processors, you must declare the tables
as extern
within the kernel source file as well as
the graph class definition file. Then, the actual table definition needs to be
specified in a separate header file that is attached as a property to the kernel as
shown below.
#include <adf.h>
extern int32 lutarray[8];
class simple_lut_graph : public adf::graph {
public:
kernel k;
parameter p;
simple_lut_graph() {
k = kernel::create(simple);
p = parameter::array(lutarray);
connect<>(p,k);
std::vector<std::string> myheaders;
myheaders.push_back("./user_parameter.h")
headers(k) = myheaders;
...
}
}
This ensures that the header file that defines the table is included in the final binary link wherever this kernel is used without causing re-definition errors.