一、axilite接口约束
可以看出s_axilite可以约束除掉hls::stream以外的其他参数类型。
二、关于axilite约束建议
1.xilinx建议对分组到同一个axilite接口的端口不要再使用额外的IO协议,当然你可以可以额外约束,只要不出问题即可,
只是不推荐而已
2.对参数array数据的优化
案例一:axilite + RAM
void function_top
(
hls::stream<ap_axiu<PIX_W*N_PIX,1,1,1> >& src,
hls::stream<ap_axiu<PIX_W*N_PIX,1,1,1> >& dst,
ap_uint<32> param_arr[512]
){
//#pragma HLS INTERFACE ap_stable port=param_arr
#pragma HLS RESOURCE variable=param_arr core=RAM_2P_BRAM
//#pragma HLS ARRAY_PARTITION variable=param_arr complete dim=1
#pragma HLS INTERFACE axis register both port=src
#pragma HLS INTERFACE axis register both port=dst
#pragma HLS INTERFACE s_axilite port=return bundle=CONTROL_BUS
#pragma HLS INTERFACE s_axilite port=param_arr bundle=CONTROL_BUS
//用户逻辑
}
案例二:axilite + ap_memory
void function_top
(
hls::stream<ap_axiu<PIX_W*N_PIX,1,1,1> >& src,
hls::stream<ap_axiu<PIX_W*N_PIX,1,1,1> >& dst,
ap_uint<32> param_arr[512]
){
//#pragma HLS INTERFACE ap_stable port=param_arr
//#pragma HLS RESOURCE variable=param_arr core=RAM_2P_BRAM
//#pragma HLS ARRAY_PARTITION variable=param_arr complete dim=1
#pragma HLS INTERFACE axis register both port=src
#pragma HLS INTERFACE axis register both port=dst
#pragma HLS INTERFACE s_axilite port=return bundle=CONTROL_BUS
#pragma HLS INTERFACE s_axilite port=param_arr bundle=CONTROL_BUS
//用户逻辑
}
案例三:axilite + ap_stable数组
void function_top
(
hls::stream<ap_axiu<PIX_W*N_PIX,1,1,1> >& src,
hls::stream<ap_axiu<PIX_W*N_PIX,1,1,1> >& dst,
ap_uint<32> param_arr[512]
){
#pragma HLS INTERFACE ap_stable port=param_arr
//#pragma HLS RESOURCE variable=param_arr core=RAM_2P_BRAM
//#pragma HLS ARRAY_PARTITION variable=param_arr complete dim=1
#pragma HLS INTERFACE axis register both port=src
#pragma HLS INTERFACE axis register both port=dst
#pragma HLS INTERFACE s_axilite port=return bundle=CONTROL_BUS
#pragma HLS INTERFACE s_axilite port=param_arr bundle=CONTROL_BUS
//用户逻辑
}
上述三种案例都是将接口综合为axilite接口的bram接口,也就是axilite_bram接口进行访问!!!!
案例四:axilite寄存器
void function_top
(
hls::stream<ap_axiu<PIX_W*N_PIX,1,1,1> >& src,
hls::stream<ap_axiu<PIX_W*N_PIX,1,1,1> >& dst,
ap_uint<32> param_arr[512]
){
//#pragma HLS INTERFACE ap_stable port=param_arr
//#pragma HLS RESOURCE variable=param_arr core=RAM_2P_BRAM
#pragma HLS ARRAY_PARTITION variable=param_arr complete dim=1
#pragma HLS INTERFACE axis register both port=src
#pragma HLS INTERFACE axis register both port=dst
#pragma HLS INTERFACE s_axilite port=return bundle=CONTROL_BUS
#pragma HLS INTERFACE s_axilite port=param_arr bundle=CONTROL_BUS
//用户逻辑
}
上述四种案例中,由于使用了axilite接口,vivado hls保留地址0x0000到0x000c,用于IO协议信号和中断信号。
// ==============================================================
// CONTROL_BUS
// 0x000 : Control signals
// bit 0 - ap_start (Read/Write/COH)
// bit 1 - ap_done (Read/COR)
// bit 2 - ap_idle (Read)
// bit 3 - ap_ready (Read)
// bit 7 - auto_restart (Read/Write)
// others - reserved
// 0x004 : Global Interrupt Enable Register
// bit 0 - Global Interrupt Enable (Read/Write)
// others - reserved
// 0x008 : IP Interrupt Enable Register (Read/Write)
// bit 0 - Channel 0 (ap_done)
// bit 1 - Channel 1 (ap_ready)
// others - reserved
// 0x00c : IP Interrupt Status Register (Read/TOW)
// bit 0 - Channel 0 (ap_done)
// bit 1 - Channel 1 (ap_ready)
// others - reserved
// 0x800 ~
// 0xfff : Memory 'param_mem_V' (512 * 32b)
// Word n : bit [31:0] - param_arr_V[n]
// (SC = Self Clear, COR = Clear on Read, TOW = Toggle on Write, COH = Clear on Handshake)
关于如何保证传输参数和获取参数的正确性:
float a=3.0f,r1;
u32 ua,ur1;
// cast float “a” to type U32
XCaculate_SetA(&calculate,*((u32*)&a));
ur1=XCaculate_GetR1(&caculate);
// cast return type U32 to float type for “r1”
r1=*((float*)&ur1);
四、HLS模块的函数的一次性执行流程
1.使用中断函数来判定期望的中断工作方式
2.为块输入端口加载寄存器值。在以上示例中,此操作是使用 API 函数 XExample_Set_a、XExample_Set_b 和
XExample_Set_c_i 来执行的。
3.使用 XExample_Start 将 ap_start 位设置为 1,以开始执行函数。此寄存器为自我清除型寄存器,如以上头文
件中所述。完成一次传输事务后,此块将暂停操作。
4.允许执行此函数。解决生成的所有中断。
5.读取输出寄存器。在以上示例中,这是使用 API 函数 XExample_Get_c_o_vld(用于确认数据有效)和
XExample_Get_c_o 来执行的。
需要注意的是这个流程是是完成一次函数调度,如果要多次调度函数,那么就重复上述步骤。
五、HLS模块的函数的连续性执行流程
1.使用中断函数来判定期望的中断工作方式。
2.为块输入端口加载寄存器值。在以上示例中,此操作是使用 API 函数 XExample_Set_a、XExample_Set_a 和
XExample_Set_c_i 来执行的。
3.使用 API XExample_EnableAutoRestart 设置自动启动函数
4.允许执行此函数。个别端口 I/O 协议将同步通过时钟处理的数据。
5.解决生成的所有中断。执行此操作期间可访问输出寄存器,但数据可能多次发生变化。
6.使用 API 函数 XExample_DisableAutoRestart 来停止执行。
7.读取输出寄存器。在以上示例中,此操作是使用 API 函数 XExample_Get_c_o 和 XExample_Set_c_o_vld 来
执行的
注意:XExample_EnableAutoRestart表示将ap_start一直拉高,也就是一轮处理完成后,ap_start会自动拉高,不需要
设计者再次在代码中执行ap_start拉高的过程。
六、MCU or ARM控制HLS IP CORE流程
1.创建HLS IP硬件实例
2.查找器件配置
3.初始化器件
4.设置HLS模块的的输入参数
5.启动器件并读取结果
#include "xexample.h" // Device driver for HLS HW block
#include "xparameters.h"
// HLS HW instance
//1.创建HLS IP硬件实例
XExample HlsExample;
XExample_Config *ExamplePtr
int main() {
int res_hw;
// Look Up the device configuration
//2.查找器件配置
ExamplePtr = XExample_LookupConfig(XPAR_XEXAMPLE_0_DEVICE_ID);
if (!ExamplePtr) {
print("ERROR: Lookup of accelerator configuration failed.\n\r");
return XST_FAILURE;
}
// Initialize the Device
3.初始化器件
status = XExample_CfgInitialize(&HlsExample, ExamplePtr);
if (status != XST_SUCCESS) {
print("ERROR: Could not initialize accelerator.\n\r");
exit(-1);
}
//Set the input parameters of the HLS block
//4.设置HLS模块的的输入参数
XExample_Set_a(&HlsExample, 42);
XExample_Set_b(&HlsExample, 12);
XExample_Set_c_i(&HlsExample, 1);
// Start the device and read the results
//5.启动器件并读取结果
XExample_Start(&HlsExample);//这个start只是拉高一次ap_start,如果你要多次进行处理,就需要使用auto_start
do {
res_hw = XExample_Get_c_o(&HlsExample);
} while (XExample_Get_c_o(&HlsExample) == 0); // wait for valid data output
print("Detected HLS peripheral complete. Result received.\n\r");
}