Инструмент жалуется, что не может работать с бинарными операторами в 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.Это структура со следующим форматом (см. Стр. 110 в UG902 для Vivado HLS 2017.1.):
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
.Или вы можете использовать 2 цикла шины для передачи одного элемента.Обратите внимание, что если вы хотите преобразовать 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
, которые можно использовать для передачи данных по простой шине.
Наконец, я хочу подчеркнуть, что вы всегда должны сначала отлаживать свой код в программном обеспечении .Есть много ошибок, которые трудно решить, основываясь только на результатах синтеза.Некоторые сообщения, как правило, указывают на людей в неправильном направлении.Я рекомендую сначала отладить свой код, используя функциональность симуляции Си.Кроме того, вы можете скомпилировать код вне Vivado HLS с помощью обычного компилятора C, такого как gcc
.Я также рекомендую использовать средство проверки памяти, такое как valgrind
, чтобы гарантировать, что ваш код не записывает внешние границы массива и т. Д. Инструмент не всегда находит эти проблемы, но приводит к неработоспособному оборудованию.
Iдумаю, что это решение, которое вы ищете:
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;
}
}
}