AI 引擎编译器会尝试以尽可能高效的方式来为缓冲器、查找表和运行时参数分配缓冲器。但您可能想要在存储器中显式控制这些缓冲器的布局。与本节先前所示内核相似,内核端口上推断的缓冲器也可以使用位置约束来约束为映射到特定拼块、存储体甚或是地址偏移,如以下示例所示。
#include <adf.h>
#include "kernels.h"
#define NUMCORES (COLS*ROWS)
using namespace adf;
template <int COLS, int ROWS, int STARTCOL, int STARTROW>
class indep_nodes_graph2 : public graph {
public:
kernel kr[NUMCORES];
port<input> datain[NUMCORES] ;
port<output> dataout[NUMCORES] ;
indep_nodes_graph() {
for (int i = 0; i < COLS; i++) {
for (int j = 0; j < ROWS; j++) {
int k = i*ROWS + j;
kr[k] = kernel::create(mykernel);
source(kr[k]) = "kernels/kernel.cc";
runtime<ratio>(kr[k]) = 0.9;
location<kernel>(kr[k]) = tile(STARTCOL+i, STARTROW+j); // kernel location
location<buffer>(kr[k].in[0]) =
{ address(STARTCOL+i, STARTROW+j, 0x0),
address(STARTCOL+i, STARTROW+j, 0x2000) }; // double buffer location
location<stack>(kr[k]) = bank(STARTCOL+i, STARTROW+j, 2); // stack location
location<buffer>(kr[k].out[0]) = location<kernel>(kr[k]); // relative buffer location
}
}
for (int i = 0; i < NUMCORES; i++) {
connect(datain[i], kr[i].in[0]);
connect(kr[i].out[0], dataout[i]);
}
};
};
在前述代码中,端口 kr[k].in[0]
处的双缓冲器位置约束到特定的存储器拼块地址偏移,此偏移是使用 address(col,row,offset)
构造函数创建的。此外,执行内核实例 kr[k]
的处理器的系统存储器(包括同步缓冲器、栈和静态堆)的位置使用 bank(col,row,bankid)
构造函数来约束到特定的存储体。最后,连接到端口 kr[k].out[0]
的缓冲器的拼块位置约束到内核实例 kr[k]
所在的拼块。在内核缓冲器端口上会应用缓冲器位置约束。
第二个示例演示了将乒乓缓冲器的缓冲器约束添加到约束文件的方式,以及
--constraints
选项为 aiecompiler
使用该约束文件的方式。{
"PortConstraints": {
"gr.k[0].in[0]": {
"buffers": [{
"column": 16,
"row": 1,
"bankId": 0,
"offset": 16320
}, {
"column": 16,
"row": 1,
"bankId": 3,
"offset": 0
}]
}
}
}
如果计算图包含 RTP 端口,那么还可选择约束另一个选择器码字,如下所示(PING、PONG 和选择器字):
{
"PortConstraints": {
"gr.fir24.in[1]": {
"buffers": [{
"column": 17,
"row": 1,
"bankId": 0,
"offset": 16320
}, {
"column": 17,
"row": 1,
"bankId": 3,
"offset": 0
}, {
"column": 18,
"row": 1,
"bankId": 0,
"offset": 16224
}]
}
}
}
重要: 使用位置约束构造函数及其之间的等同关系即可制定出编译器必须遵循的高精度映射决策。但您必须谨慎操作,因为这样会创建编译器无法满足的约束。例如,编译器无法允许将两个缓冲器映射到同一个地址偏移。