我目前正在尝试做一些关于Vivado HLS的项目。但是,我得到了一个错误,如合成过程中的标题所示。但是,出现了以下错误:
错误:**二进制表达式('double‘和'datau32’(又名'ap_axiu<32,2,5,6>‘) imgOut= (0.2126*Imgincoord + 0.7152*Imgincoord+1 + 0.0722*Imgincoord+2)的无效操作数
这是我的HLS密码:
#include "core.h"
void imgreading(hls::stream<datau32> &inStream, datau32 Imgin[imagesize])
{
for(int i=0;i<imagesize;i++)
{
Imgin[i]=(datau32)inStream.read();
}
}
void resize_half(hls::stream<datau32> &inStream, hls::stream<datau32> &outStream)
{
#pragma HLS INTERFACE axis port=inStream
#pragma HLS INTERFACE axis port=outStream
#pragma HLS INTERFACE s_axilite port=return bundle=CRTL_BUS
datau32 Imgin[imagesize];
imgreading (inStream,Imgin);
datau32 imgOut;
int coord=0;
#pragma HLS DATAFLOW
for (int a=0; a<240; a++) {
for(int b=0; b<320; b++){
#pragma HLS PIPELINE II=1
coord=6*(a*640+b);
imgOut= (0.2126*Imgin[coord] + 0.7152*Imgin[coord+1] + 0.0722*Imgin[coord+2]) ;
datau32 dataOutSideChannel;
dataOutSideChannel.data = imgOut;
outStream.write (dataOutSideChannel);
}
}
}发布于 2018-05-11 12:00:04
这些工具抱怨它不能处理imgOut= (0.2126*Imgin[coord] + 0.7152*Imgin[coord+1] + 0.0722*Imgin[coord+2])中的二进制操作符。二进制运算符是两个操作数的操作符,这里是*和+。正如错误消息中提到的,datau32是ap_axiu<32, 2, 5, 6>类型的。Imgin和imgOut将datau32作为基本类型。因此,消息似乎是指Imgin[...]与浮点常量(0.2126等)的乘法。
无论如何,ap_axiu是用来声明AXI总线的。它是一个具有以下格式的结构(关于Vivado HLS 2017.1,请参见UG902第110页):
template<int D,int U,int TI,int TD>
struct ap_axiu{
ap_uint<D> data;
ap_uint<D/8> keep;
ap_uint<D/8> strb;
ap_uint<U> user;
ap_uint<1> last;
ap_uint<TI> id;
ap_uint<TD> dest;
};所以你要做的是用一个结构乘以一个浮点常量。这在C++中是不允许的。
如果您打算使用AXI总线,则必须使用结构的data字段来传递数据。将整数data字段与double相乘的结果是另一个double。double是64位宽,所以你也必须处理这个差异。您可以使用float类型的常量,这可能足够精确。或者你可以把你的AXI巴士加宽。或者您可以通过转换到float来降低计算后的精度。或者您可以使用两个总线周期来传输单个元素。请注意,如果要将double或float转换为整数,则必须使用reinterpret_cast以避免丢失精度。请注意,您还必须为ap_axiu结构的所有其他字段赋值。请注意,您还必须为ap_axiu结构的所有其他字段(keep、strb等)赋值。
使用AXI总线的一种更简单的方法是将inStream和outStream声明为数组,例如ap_uint<32> inStream[320*240]。握手(TREADY和TVALID)是自动处理的。如果您需要所谓的侧信道(剩下的信号如TLAST或TUSER),则不能使用此方法。例如,如果您想要传输数据包而不是连续流(可以使用TLAST完成),或者如果您的数据大小不是总线大小的倍数,则需要一个字节启用信号(TKEEP)。
我还可以想象,您从未打算使用AXI总线。有些类型(如ap_uint和ap_fixed )可用于在普通总线上提交数据。
最后,我想强调的是,--您应该始终在软件优先中调试您的代码。有许多错误是很难解决的基础上的综合输出。有些信息往往指向错误的方向。我建议您首先使用C模拟功能调试代码。或者,您可以使用常规C编译器(如gcc )在Vivado HLS之外编译代码。我还建议使用内存检查器(如valgrind )来确保代码不会编写外部数组边界等。该工具并不总是发现这些问题,但它确实会导致无法使用的硬件。
我认为这是你正在寻找的解决方案:
void resize_half(ap_uint<32> inAXI[640 * 480 * 3], ap_uint<32> outAXI[320 * 240])
{
#pragma HLS INTERFACE axis port=inAXI
#pragma HLS INTERFACE axis port=outAXI
#pragma HLS INTERFACE s_axilite port=return bundle=CRTL_BUS
#pragma HLS dataflow
hls::stream<ap_uint<32> > Stream[3];
for (int i = 0; i < 480; i++)
for (int j = 0; j < 640; j++)
for (int k = 0; k < 3; k++)
{
#pragma HLS PIPELINE II=1
ap_uint<32> value = inAXI[3 * (640 * i + j) + k];
if (i % 2 == 0 && j % 2 == 0)
Stream[k].write(value);
}
for (int a = 0; a < 240; a++)
{
for (int b = 0; b < 320; b++)
{
#pragma HLS PIPELINE II=1
ap_uint<32> x = Stream[0].read();
ap_uint<32> y = Stream[1].read();
ap_uint<32> z = Stream[2].read();
outAXI[320 * a + b] = 0.2126 * x + 0.7152 * y + 0.0722 * z;
}
}
}https://stackoverflow.com/questions/50270744
复制相似问题