我正在写一些使用Vitis HLS的代码。代码如下:
#include "algo.h"
void find_peaks(ap_uint<14> input[NDATA], bool *peak, ap_uint<14> *start_time, ap_uint<14> *end_time, ap_uint<14> *peak_time, ap_uint<14> *peak_value, ap_uint<14> *sum_value){
ap_uint<14> local_start_time = 0;
ap_uint<14> local_end_time = 0;
ap_uint<14> local_peak_time = 0;
ap_uint<14> local_peak_value = 0;
ap_uint<14> local_sum_value = 0;
ap_uint<14> width = 0;
bool prev_peak = false;
for (ap_uint<14> i = 0; i<NDATA; i++){
prev_peak = *peak;
*peak = input[i]>20;
local_start_time = (*peak && !prev_peak)? i:local_start_time;
local_end_time = *peak? i:local_end_time;
local_peak_time = (*peak && (input[i]>local_peak_value))? i:local_peak_time;
local_peak_value = (*peak && (input[i]>local_peak_value))? input[i]:local_peak_value;
local_sum_value += *peak ? input[i]:ap_uint<14>(0);
width = local_end_time - local_start_time;
*start_time = (!*peak && prev_peak && (width>3))? local_start_time: *start_time ;
*end_time = (!*peak && prev_peak && (width>3))? local_end_time: *end_time ;
*peak_time = (!*peak && prev_peak && (width>3))? local_peak_time: *peak_time ;
*peak_value = (!*peak && prev_peak && (width>3))? local_peak_value: *peak_value ;
*sum_value = (!*peak && prev_peak && (width>3))? local_sum_value: *sum_value ;
}
}其中,NDATA在输入文件中定义为64。这是可行的,并且可以很好地进行合成。当我尝试使用#pragmas来优化它时,问题就开始了。其中一个主要需求是代码要流水线化。我尝试使用以下两种方法:
#pragma HLS pipeline II=1 style=flp考虑到它不能足够快地读取输入,这是可以理解的,我使用了推荐的修复方法,即使用以下命令将输入拆分为单独的寄存器
#pragma HLS ARRAY_PARTITION variable=input complete这就是问题所在: Vitis停止了合成它的能力,并给出了以下错误:
ERROR: [HLS 214-247] in function 'find_peaks(ap_uint<14>*, bool*, ap_uint<14>*, ap_uint<14>*, ap_uint<14>*, ap_uint<14>*, ap_uint<14>*) (.12)': Cannot apply array transformation pragma/directive because of pointer selection. (src/algo.cpp:21:22)我还没有找到任何相关的文档。有没有人知道是什么原因造成的,或者我该如何修复它?
发布于 2021-10-07 11:56:34
首先:在哪里应用管道?在函数级别还是在循环级别?
volatile (否则编译器可能认为您只关心它们在循环结束时的最后一个值)我不完全确定为什么在插入编译指示时会出现问题,但您也在处理指针,而指针(以及指针算法)与HLS不能很好地配合。
我的第一个建议是将指针参数替换为按引用传递参数,如下所示:
void find_peaks(ap_uint<14> input[NDATA], volatile bool &peak,
volatile ap_uint<14> &start_time, volatile ap_uint<14> &end_time,
volatile ap_uint<14> &peak_time, volatile ap_uint<14> &peak_value,
volatile ap_uint<14> &sum_value) {
ap_uint<14> local_start_time = 0;
ap_uint<14> local_end_time = 0;
ap_uint<14> local_peak_time = 0;
ap_uint<14> local_peak_value = 0;
ap_uint<14> local_sum_value = 0;
ap_uint<14> width = 0;
bool prev_peak = false;
for (int i = 0; i < NDATA; i++){
assert(i < NDATA);
prev_peak = peak;
peak = input[i] > 20;
local_start_time = (peak && !prev_peak)? i:local_start_time;
local_end_time = peak? i : local_end_time;
local_peak_time = (peak && (input[i] > local_peak_value))? i : local_peak_time;
local_peak_value = (peak && (input[i]>local_peak_value))? input[i] : local_peak_value;
local_sum_value += peak ? input[i] : ap_uint<14>(0);
width = local_end_time - local_start_time;
const bool cond = !peak && prev_peak && (width > 3);
start_time = cond ? local_start_time: start_time;
end_time = cond ? local_end_time: end_time;
peak_time = cond ? local_peak_time: peak_time;
peak_value = cond ? local_peak_value: peak_value;
sum_value = cond ? local_sum_value: sum_value;
}
}对于HLS来说,这应该是等价的,并且“不那么令人困惑”。
您可能希望考虑使用FIFO或缓冲区(或更好的RTL语言)来向“外部世界”通知信号的状态。使用volatile可能不是最好的,毕竟HLS更适合于其他东西,而不是真正用于时间/性能跟踪。(当然,你仍然可以尝试一下,这里有一个用HLS实现的reference )。
附注:目前我手头没有HLS,但稍后我可能会尝试合成代码,看看是否也可以插入编译指示。
https://stackoverflow.com/questions/69478217
复制相似问题