本篇博客介紹VVAS框架所支持調用的H/W(HLS)內核。H/W內核指的是使用HLS工具生成的在FPGA部分執行的硬件功能模塊。
HLS kernel創建
我們以smartcam的預處理作為例子,相關的代碼可以在參考鏈接中找到。xf_pp_pipeline的作用是將輸入圖像的格式從NV12轉換為BGR,再進行減均值和歸一化操作。xf_pp_pipeline的實現基于HLS vision library。Vitis視覺庫是為在Vitis開發環境中工作而設計的,它為在FPGA設備上加速的計算機視覺功能提供了一個軟件接口。Vitis視覺庫的功能大多與OpenCV的功能相似。更多的詳細說明可以在參考鏈接中找到。
#include "xf_pp_pipeline_config.h" void pp_pipeline_accel(ap_uint* img_inp_y, // Y Input image pointer ap_uint* img_inp_uv, // UV Input image pointer ap_uint* img_out, // output image pointer float params[2 * XF_CHANNELS(IN_TYPE, NPC)], int in_img_width, int in_img_height, int in_img_linestride, int out_img_width, // Final Output image width int out_img_height, // Final Output image height int out_img_linestride) { // Final Output image line stride #pragma HLS INTERFACE m_axi port=img_inp_y offset=slave bundle=gmem1 #pragma HLS INTERFACE m_axi port=img_inp_uv offset=slave bundle=gmem2 #pragma HLS INTERFACE m_axi port=img_out offset=slave bundle=gmem3 #pragma HLS INTERFACE m_axi port=params offset=slave bundle=gmem4 #pragma HLS INTERFACE s_axilite port=in_img_width #pragma HLS INTERFACE s_axilite port=in_img_height #pragma HLS INTERFACE s_axilite port=in_img_linestride #pragma HLS INTERFACE s_axilite port=out_img_width #pragma HLS INTERFACE s_axilite port=out_img_height #pragma HLS INTERFACE s_axilite port=out_img_linestride #pragma HLS INTERFACE s_axilite port=return ...... xf::cv::resize(rgb_mat, resize_out_mat); xf::cv::preProcess(resize_out_mat, out_mat, params); ...... }
xf_pp_pipeline_accel.cpp作為硬件的一部分,需要將它和platform結合在一起。v++將HLS kernel打包為xo文件用于后續的硬件集成。
kv260_ispMipiRx_vcu_DP是smartcam應用使用的platform,xf_pp_pipeline.cpp打包成xo對象后,通過v++鏈接為完整的硬件工程并生成xclbin文件。完整的硬件框圖如下圖所示,紅框部分為對應的HLS kernel。
Kernel調用
使用VVAS框架為xf_pp_pipeline.cpp編寫自定義驅動是要實現四個函數,分別是xlnx_kernel_start、xlnx_kernel_done、xlnx_kernel_init、xlnx_kernel_deinit。
xlnx_kernel_init()函數讀取json文件中的mean_r、mean_g、mean_b、scale_r、scale_g、scale_b。
int32_t xlnx_kernel_init(IVASKernel *handle){ ...... kernel_priv->mean_r = json_number_value(val); kernel_priv->mean_g = json_number_value(val); kernel_priv->mean_b = json_number_value(val); kernel_priv->scale_r = json_number_value(val); kernel_priv->scale_g = json_number_value(val); kernel_priv->scale_b = json_number_value(val); ...... }
xlnx_kernel_start()函數為HLS kernel配置參數。
int32_t xlnx_kernel_start(IVASKernel *handle, int start, IVASFrame *input[MAX_NUM_OBJECT], IVASFrame *output[MAX_NUM_OBJECT]) { ...... ivas_register_write(handle, &(input[0]->props.width), sizeof(uint32_t), 0x40); /* In width */ ivas_register_write(handle, &(input[0]->props.height), sizeof(uint32_t), 0x48); /* In height */ ivas_register_write(handle, &(input[0]->props.stride), sizeof(uint32_t), 0x50); /* In stride */ ivas_register_write(handle, &(output[0]->props.width), sizeof(uint32_t), 0x58); /* Out width */ ivas_register_write(handle, &(output[0]->props.height), sizeof(uint32_t), 0x60); /* Out height */ ivas_register_write(handle, &(output[0]->props.width), sizeof(uint32_t), 0x68); /* Out stride */ ivas_register_write(handle, &(input[0]->paddr[0]), sizeof(uint64_t), 0x10); /* Y Input */ ivas_register_write(handle, &(input[0]->paddr[1]), sizeof(uint64_t), 0x1C); /* UV Input */ ivas_register_write(handle, &(output[0]->paddr[0]), sizeof(uint64_t), 0x28); /* Output */ ivas_register_write(handle, &(kernel_priv->params->paddr[0]), sizeof(uint64_t), 0x34); /* Params */ ivas_register_write(handle, &start, sizeof(uint32_t), 0x0); /* start */ ...... }
xlnx_kernel_deinit()函數用來釋放不需要的句柄。
uint32_t xlnx_kernel_deinit(IVASKernel *handle) { ResizeKernelPriv *kernel_priv; kernel_priv = (ResizeKernelPriv *)handle->kernel_priv; ivas_free_buffer (handle, kernel_priv->params); free(kernel_priv); return 0; }
xlnx_kernel_done()函數進行超時檢測。
int32_t xlnx_kernel_done(IVASKernel *handle) { uint32_t val = 0, count = 0; do { ivas_register_read(handle, &val, sizeof(uint32_t), 0x0); /* start */ count++; if (count > 1000000) { printf("ERROR: kernel done wait TIME OUT !!\n"); return 0; } } while (!(0x4 & val)); return 1; }
通過這四個函數就完成了VVAS自定義插件的設計。在smartcam應用運行時,通過命令行gst-launch-1.0 -v filesrc XXXXXX ! queue ! vvas_xmultisrc kconfig="/opt/xilinx/kv260-smartcam/share/vvas/facedetect/preprocess.json" ! XXXXXX完成插件的調用。
其中preprocess.json的內容為:
{ "xclbin-location":"/lib/firmware/xilinx/kv260-smartcam/kv260-smartcam.xclbin", "vvas-library-repo": "/opt/xilinx/kv260-smartcam/lib", "element-mode": "transform", "kernels": [ { "kernel-name": "pp_pipeline_accel:{pp_pipeline_accel_1}", "library-name": "libvvas_xpp.so", "config": { "debug_level" : 1, "mean_r": 123, "mean_g": 117, "mean_b": 104, "scale_r": 1, "scale_g": 1, "scale_b": 1 } } ] }
本文簡要介紹了VVAS調用HLS生成的硬件加速器的主要流程,更多的細節可以參考VVAS手冊。
責任編輯:彭菁
-
加速器
+關注
關注
2文章
785瀏覽量
37134 -
硬件
+關注
關注
11文章
3108瀏覽量
65833 -
HLS
+關注
關注
1文章
128瀏覽量
23907
發布評論請先 登錄
相關推薦
評論