SDSoC: HLS函数中仅使用数组部分内容作为序列输入的实现方法
针对Xilinx SDSoC/HLS二维数组列数据流式访问的高效方案
完全有成熟的低开销实现方案,核心是利用HLS流优化、地址偏移访问和SDSoC显式数据移动机制,可实现零额外拷贝的流式顺序访问,具体方案如下:
方案1:加速函数侧直接做地址偏移+流转换
主函数不需要做额外的数组拆分,直接把sds_alloc分配的一维数组基地址、目标列索引、参数N传入PL加速函数即可,你描述的存储结构下,第k列对应的一维数组起始偏移为k*N。
加速函数代码示例
#include <hls_stream.h> void col_process(int *base_arr, int col1_idx, int col2_idx, int N, int *output) { // 配置AXI接口,depth按需调整为你实际的N最大值 #pragma HLS INTERFACE m_axi port=base_arr offset=slave bundle=gmem depth=10000 #pragma HLS INTERFACE s_axilite port=col1_idx bundle=ctrl #pragma HLS INTERFACE s_axilite port=col2_idx bundle=ctrl #pragma HLS INTERFACE s_axilite port=N bundle=ctrl #pragma HLS INTERFACE s_axilite port=return bundle=ctrl hls::stream<int> strm_col1, strm_col2; // 流深度配置为32/64即可掩盖DMA latency,避免流水线断流 #pragma HLS STREAM variable=strm_col1 depth=32 #pragma HLS STREAM variable=strm_col2 depth=32 // 开启数据流优化,让读列和处理逻辑并行执行 #pragma HLS DATAFLOW // 第一阶段:连续读取两列数据写入流,完全顺序访问 read_col: for(int i=0; i<N; i++) { #pragma HLS PIPELINE II=1 // 该偏移计算匹配你描述的「每列对应一维数组连续N个元素」的存储结构 strm_col1.write(base_arr[col1_idx * N + i]); strm_col2.write(base_arr[col2_idx * N + i]); } // 第二阶段:从流中取数执行业务处理 process: for(int i=0; i<N; i++) { #pragma HLS PIPELINE II=1 int val1 = strm_col1.read(); int val2 = strm_col2.read(); // 此处替换为你的实际处理逻辑 output[i] = val1 + val2; } }
该方案优势是完全无额外内存拷贝,SDSoC会自动识别你访问的两段连续地址范围,控制DMA只搬运需要的2*N个元素到PL,不会读取整个大数组。
方案2:主函数侧显式指定搬运范围(适合超大数组场景)
如果担心SDSoC自动识别数据范围不准,可以在主函数侧显式标记需要搬运的内存段,确保无多余数据移动:
主函数代码示例
#include <sds_lib.h> #define N 1024 #define M 128 int main() { int *arr = (int *)sds_alloc(N*M*sizeof(int)); // 数组填充逻辑省略 int target_col1 = 2, target_col2 = 5; // 示例要处理第2、5列 int *col1_addr = arr + target_col1 * N; int *col2_addr = arr + target_col2 * N; int *output = (int *)sds_alloc(N*sizeof(int)); // 显式标记要搬运的只读内存段 sds_mem_map(col1_addr, N*sizeof(int), SYS_MEM_FULL_CACHE, SDS_MMAP_READ_ONLY); sds_mem_map(col2_addr, N*sizeof(int), SYS_MEM_FULL_CACHE, SDS_MMAP_READ_ONLY); // 调用PL加速函数 col_process(arr, target_col1, target_col2, N, output); // 释放内存映射 sds_mem_unmap(col1_addr, N*sizeof(int)); sds_mem_unmap(col2_addr, N*sizeof(int)); // 后续结果处理逻辑省略 sds_free(arr); sds_free(output); return 0; }
内容的提问来源于stack exchange,提问作者Nick
相关产品推荐
相关产品推荐

