From c37a9fa768744308d523366eb464d4e6d8bb4a88 Mon Sep 17 00:00:00 2001 From: Filip Leonarski Date: Tue, 24 Oct 2023 18:05:48 +0200 Subject: [PATCH] FPGA: Add multipixel - handle division by 2 and 4 for multipixels. --- fpga/hls/add_multipixel.cpp | 112 ++++++++++++++++++++++++++++++--- fpga/hls/add_multipixel_tb.cpp | 44 +++++-------- tests/CMakeLists.txt | 3 +- 3 files changed, 122 insertions(+), 37 deletions(-) diff --git a/fpga/hls/add_multipixel.cpp b/fpga/hls/add_multipixel.cpp index dba21b88..22feb1a1 100644 --- a/fpga/hls/add_multipixel.cpp +++ b/fpga/hls/add_multipixel.cpp @@ -8,6 +8,42 @@ struct add_multipixel_packet { ap_uint<1> last; }; +ap_uint<512> divide_by_two(const ap_uint<512> &input) { +#pragma HLS PIPELINE II=1 + ap_int<16> val[32]; + unpack32(input, val); + for (int i = 0; i < 32; i++) { + if ((val[i] == INT16_MIN) || (val[i] == INT16_MAX)) + val[i] = val[i]; + else + val[i] = val[i] / 2; + } + return pack32(val); +} + +void divide_last_by_two(ap_uint<512> &input) { +#pragma HLS PIPELINE II=1 + ap_int<16> val[32]; + unpack32(input, val); + if ((val[31] == INT16_MIN) || (val[31] == INT16_MAX)) + val[31] = val[31]; + else + val[31] = val[31] / 2; + input = pack32(val); +} + + +void divide_first_by_two(ap_uint<512> &input) { +#pragma HLS PIPELINE II=1 + ap_int<16> val[32]; + unpack32(input, val); + if ((val[0] == INT16_MIN) || (val[0] == INT16_MAX)) + val[0] = val[0]; + else + val[0] = val[0] / 2; + input = pack32(val); +} + void add_multipixel_in_stream(STREAM_512 &data_in, hls::stream &data_out) { packet_512_t packet_in; @@ -22,6 +58,40 @@ void add_multipixel_in_stream(STREAM_512 &data_in, data_out << add_multipixel_packet{.data = packet_in.data, .user = packet_in.user, .last = packet_in.last}; } +void add_multipixel_div(hls::stream &data_in, + hls::stream &data_out) { +#pragma HLS INTERFACE axis port=data_in +#pragma HLS INTERFACE axis port=data_out + add_multipixel_packet packet_in, packet_out; + data_in >> packet_in; + data_out << packet_in; + ap_uint<1> add_multipixel = ((ACT_REG_MODE(packet_in.data) & MODE_ADD_MULTIPIXEL)) ? 1 : 0; + + data_in >> packet_in; + if (!add_multipixel) { + while (!packet_in.user) { +#pragma HLS PIPELINE II=1 + data_out << packet_in; + data_in >> packet_in; + } + } else { + while (!packet_in.user) { +#pragma HLS PIPELINE II=32 + for (int i = 0; i < 32; i++) { + if ((i == 8 - 1) || (i == 2 * 8 - 1) || (i == 3 * 8 - 1)) + divide_last_by_two(packet_in.data); + + if ((i == 8) || (i == 2 * 8) || (i == 3 * 8)) + divide_first_by_two(packet_in.data); + data_out << packet_in; + data_in >> packet_in; + } + } + } + data_out << packet_in; +} + + void add_multipixel_cols(hls::stream &data_in, hls::stream &data_out) { #pragma HLS INTERFACE axis port=data_in @@ -48,7 +118,7 @@ void add_multipixel_cols(hls::stream &data_in, ap_uint<512> save = packet_in.data; data_in >> packet_in; for (int i = 1; i < 8; i++) { - packet_out.data(511-8,0) = save(511,16); + packet_out.data(511-16,0) = save(511,16); packet_out.data(511,512-16) = packet_in.data(15, 0); data_out << packet_out; save = packet_in.data; @@ -56,10 +126,18 @@ void add_multipixel_cols(hls::stream &data_in, } packet_out = packet_in; packet_out.data = save(511,16); + packet_out.data(511, 512-16) = packet_out.data(511-16, 512-32); data_out << packet_out; - save = 0; + for (int k = 1; k < 4; k++) { + if (k == 1) { + save = packet_in.data(15, 0); + } else if (k == 2) { + save(31,16) = save(15,0); + } else if (k == 3) { + save(63,48) = save(47,32); + } for (int i = 0; i < 8; i++) { packet_out.data(511, (k * 2 - 1) * 16) = packet_in.data(511 - (k * 2 - 1) * 16, 0); packet_out.data((k * 2 - 1) * 16 - 1, 0) = save; @@ -67,6 +145,10 @@ void add_multipixel_cols(hls::stream &data_in, data_out << packet_out; data_in >> packet_in; } + if (k == 1) + save(47, 32) = packet_in.data(15,0); + else if (k == 2) + save(79, 64) = packet_in.data(15,0); } packet_out.data = save; @@ -105,8 +187,8 @@ void add_multipixel_line(hls::stream &data_in, #pragma HLS PIPELINE II=66 ap_uint<512> packet[33]; for (int i = 0; i < 33; i++) { - packet[i] = packet_in.data; - data_out << packet_in; + packet[i] = divide_by_two(packet_in.data); + data_out << add_multipixel_packet{.data = packet[i], .user = 0, .last = 0}; data_in >> packet_in; } for (int i = 0; i < 33; i++) { @@ -189,8 +271,24 @@ void add_multipixel(STREAM_512 &data_in, STREAM_512 &data_out) { hls::stream stream_0; hls::stream stream_1; hls::stream stream_2; + hls::stream stream_3; + +#ifndef JFJOCH_HLS_NOSYNTH add_multipixel_in_stream(data_in, stream_0); - add_multipixel_cols(stream_0, stream_1); - add_multipixel_line(stream_1, stream_2); - add_multipixel_output(stream_2, data_out); + add_multipixel_div(stream_0, stream_1); + add_multipixel_cols(stream_1, stream_2); + add_multipixel_line(stream_2, stream_3); + add_multipixel_output(stream_3, data_out); +#else + std::vector multipix_cores; + + multipix_cores.emplace_back([&] {add_multipixel_in_stream(data_in, stream_0);}); + multipix_cores.emplace_back([&] {add_multipixel_div(stream_0, stream_1);}); + multipix_cores.emplace_back([&] {add_multipixel_cols(stream_1, stream_2);}); + multipix_cores.emplace_back([&] {add_multipixel_line(stream_2, stream_3);}); + multipix_cores.emplace_back([&] {add_multipixel_output(stream_3, data_out);}); + + for (auto &i : multipix_cores) + i.join(); +#endif } diff --git a/fpga/hls/add_multipixel_tb.cpp b/fpga/hls/add_multipixel_tb.cpp index 4206e32a..6cfbefaa 100644 --- a/fpga/hls/add_multipixel_tb.cpp +++ b/fpga/hls/add_multipixel_tb.cpp @@ -1,6 +1,7 @@ // Copyright (2019-2023) Paul Scherrer Institute #include "hls_jfjoch.h" +#include "../../common/RawToConvertedGeometryCore.h" int main() { @@ -9,12 +10,14 @@ int main() { STREAM_512 input; STREAM_512 output; - size_t nframes = 1; - - std::vector input_frame(nframes * RAW_MODULE_SIZE), output_frame(nframes * 257 * 64 * 32); - for (int i = 0; i < nframes * RAW_MODULE_SIZE; i++) { + std::vector input_frame(RAW_MODULE_SIZE), input_frame_transformed(CONVERTED_MODULE_SIZE), + output_frame(257 * 64 * 32); + for (int i = 0; i < RAW_MODULE_SIZE; i++) input_frame[i] = i % INT16_MAX; - } + + TransferModuleAdjustMultipixels(input_frame_transformed.data(), input_frame.data(), + CONVERTED_MODULE_COLS, INT16_MIN, INT16_MAX); + auto input_frame_512 = (ap_uint<512>*) input_frame.data(); auto output_frame_512 = (ap_uint<512>*) output_frame.data(); @@ -22,7 +25,7 @@ int main() { ACT_REG_MODE(action_control) = MODE_ADD_MULTIPIXEL; input << packet_512_t { .data = action_control, .user = 0 }; - for (int i = 0; i < nframes * RAW_MODULE_SIZE * sizeof(uint16_t) / 64; i++) + for (int i = 0; i < RAW_MODULE_SIZE * sizeof(uint16_t) / 64; i++) input << packet_512_t { .data = input_frame_512[i], .user = 0 }; input << packet_512_t { .user = 1 }; @@ -31,40 +34,23 @@ int main() { if (input.size() != 0) ret = 1; - if (output.size() != nframes * (257 * 64) + 2) + if (output.size() != (257 * 64) + 2) ret = 1; output.read(); - for (int i = 0; i < nframes * 257 * 64 ; i++) + for (int i = 0; i < 257 * 64 ; i++) output_frame_512[i] = output.read().data; output.read(); size_t diff = 0; - for (int line = 1; line < 511; line++) { - int new_line = line + (line / 256) * 2 - 1; - for (int col = 1; col < 1023; col++) { - int new_col = col + (col / 256) * 2 - 1; - if (output_frame[new_line * 1028 + new_col] != input_frame[line * 1024 + col]) + for (int line = 0; line < 512; line++) { + for (int col = 0; col < 1027; col++) { + if (output_frame[line * 1028 + col] != input_frame_transformed[(line + 1) * 1030 + (col+1)]) diff++; } + } - for (int col = 1; col < 1023; col++) { - int new_col = col + (col / 256) * 2 - 1; - if (output_frame[254 * 1028 + new_col] != input_frame[255 * 1024 + col]) - diff++; - if (output_frame[255 * 1028 + new_col] != input_frame[255 * 1024 + col]) - diff++; - } - - - for (int col = 1; col < 1023; col++) { - int new_col = col + (col / 256) * 2 - 1; - if (output_frame[256 * 1028 + new_col] != input_frame[256 * 1024 + col]) - diff++; - if (output_frame[257 * 1028 + new_col] != input_frame[256 * 1024 + col]) - diff++; - } if (diff > 0) { ret = 1; std::cout << diff << std::endl; diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt index a5955c27..a0976fd5 100644 --- a/tests/CMakeLists.txt +++ b/tests/CMakeLists.txt @@ -27,7 +27,8 @@ ADD_EXECUTABLE(CatchTest CBORTest.cpp ../tests/stream2.h ../tests/stream2.c JFConversionTest.cpp DetectorGeometryTest.cpp JFJochBrokerParserTest.cpp DetectorSetupTest.cpp DiffractionGeometryTest.cpp ROIFilterTest.cpp FPGAHLSBitshuffleTest.cpp - FPGASpotFindingUnitTest.cpp) + FPGASpotFindingUnitTest.cpp + FPGAAddMultipixelTest.cpp) target_link_libraries(CatchTest JFJochBroker JFJochReceiver JFJochWriter ImageAnalysis CommonFunctions HLSSimulation) target_include_directories(CatchTest PRIVATE .)