From 90344eb251e59caad8490e21a14bb1e992a09d9e Mon Sep 17 00:00:00 2001 From: Filip Leonarski Date: Thu, 19 Oct 2023 19:40:31 +0200 Subject: [PATCH] FPGA: Basic spot finder (i.e. only based on count threshold) as a placeholder --- fpga/hls/spot_finder.cpp | 442 +++--------------------------- fpga/hls/spot_finder.h | 109 -------- tests/FPGASpotFindingUnitTest.cpp | 380 ------------------------- 3 files changed, 32 insertions(+), 899 deletions(-) diff --git a/fpga/hls/spot_finder.cpp b/fpga/hls/spot_finder.cpp index 1a4fb11a..82f7b69a 100644 --- a/fpga/hls/spot_finder.cpp +++ b/fpga/hls/spot_finder.cpp @@ -2,323 +2,6 @@ #include "spot_finder.h" -void calc_sum(ap_uint &ext_column_sum, - const ap_uint<512> ext_old_value, - const ap_uint<512> ext_new_value) { -#pragma HLS PIPELINE II=1 - ap_int column_sum[32]; - ap_int<16> new_value[32]; - ap_int<16> old_value[32]; - - unpack32(ext_new_value, new_value); - unpack32(ext_old_value, old_value); - - for (int i = 0; i < 32; i++) { - column_sum[i] = new_value[i] - old_value[i]; - } - ext_column_sum = pack32(column_sum); -} - -void calc_sum2(ap_uint &ext_column_sum2, - const ap_uint<512> ext_old_value, - const ap_uint<512> ext_new_value) { -#pragma HLS PIPELINE II=1 - ap_int column_sum2[32]; - ap_int<16> new_value[32]; - ap_int<16> old_value[32]; - - unpack32(ext_new_value, new_value); - unpack32(ext_old_value, old_value); - - for (int i = 0; i < 32; i++) { - column_sum2[i] = new_value[i]*new_value[i] - old_value[i] * old_value[i]; - // Apparently on FPGA this is easier, than using (new-old)*(new+old) - could it be DSP mapping? - } - ext_column_sum2 = pack32(column_sum2); -} - -void calc_mask_diff(ap_uint &ext_column_valid, - const ap_uint<32> ext_old_value, - const ap_uint<32> ext_new_value) { -#pragma HLS PIPELINE II=1 - ap_int column_valid[32]; - - for (int i = 0; i < 32; i++) - column_valid[i] = ap_int(ext_new_value[i]) - ap_int(ext_old_value[i]); - - ext_column_valid = pack32(column_valid); -} - -void calc_mask(const ap_uint<512> &input, ap_uint<512> &output, ap_uint<32> &mask) { -#pragma HLS PIPELINE II=1 - ap_int<16> value[32]; - ap_uint<32> tmp_mask; - ap_uint<512> tmp_output; - - unpack32(input, value); - - for (int i = 0; i < 32; i++) { - if ((value[i] == INT16_MAX) || (value[i] == INT16_MIN)) { - tmp_mask[i] = 0; - tmp_output(i * 16 + 15, i * 16) = 0; - } else { - tmp_mask[i] = 1; - tmp_output(i * 16 + 15, i * 16) = input(i * 16 + 15, i * 16); - } - } - mask = tmp_mask; - output = tmp_output; -} - - -ap_uint<1> check_threshold(ap_int<16> val, - ap_int sum, - ap_int sum2, - ap_int valid, - strong_pixel_threshold_t strong_pixel_threshold, - ap_int<16> photon_count_threshold) { -#pragma HLS INLINE - ap_int in_minus_mean = val * valid - sum; - ap_uint variance = valid * sum2 - sum * sum; - - if ((in_minus_mean * in_minus_mean * (valid - 1) > variance * strong_pixel_threshold * valid) && - (in_minus_mean > 0) && - (val > photon_count_threshold)) - return 1; - else - return 0; -} - -ap_uint<32> check_threshold(const ap_uint<512> data_packed, - const ap_uint sum_packed, - const ap_uint sum2_packed, - const ap_uint valid_packed, - strong_pixel_threshold_t strong_pixel_threshold, - ap_int<16> photon_count_threshold) { -#pragma HLS PIPELINE II=1 - ap_int<16> data[32]; - ap_int sum[32]; - ap_int sum2[32]; - ap_int valid[32]; - - unpack32(data_packed, data); - unpack32(sum_packed, sum); - unpack32(sum2_packed, sum2); - unpack32(valid_packed, valid); - - ap_uint<32> tmp_output = 0; - - for (int i = 0; i < 32; i++) - tmp_output[i] = check_threshold(data[i], sum[i], sum2[i], valid[i], strong_pixel_threshold, photon_count_threshold); - - return tmp_output; -} - -void spot_finder_col_sum(STREAM_512 &data_in, - hls::stream &data_out, - hls::stream> &sum_out, - hls::stream> &sum2_out, - hls::stream> &valid_out) { - ap_uint<512> data_cache[(2 * FPGA_NBX + 1) * 32]; - ap_uint<32> mask_cache[(2 * FPGA_NBX + 1) * 32]; - - ap_uint sum_cache[32]; - ap_uint sum2_cache[32]; - ap_uint valid_cache[32]; - - packet_512_t packet_in; - data_in >> packet_in; - data_out << spot_finder_packet{.data=packet_in.data, .user=0}; - - data_in >> packet_in; - while (!packet_in.user) { - - for (int i = 0; i < 32; i++) { -#pragma HLS unroll - sum_cache[i] = 0; - sum2_cache[i] = 0; - valid_cache[i] = 0; - } - - for (int i = 0; i < (2 * FPGA_NBX + 1) * 32; i++) { -#pragma HLS unroll - data_cache[i] = 0; - mask_cache[i] = 0; - } - - for (int i = 0; i < (FPGA_NBX) * 32 + RAW_MODULE_SIZE * sizeof(uint16_t) / 64; i++) { -#pragma HLS PIPELINE II = 1 - ap_uint<512> packet_in_data; - ap_uint<32> packet_in_mask; - - if (i < RAW_MODULE_SIZE * sizeof(uint16_t) / 64) { - data_out << spot_finder_packet{.data=packet_in.data, .user=0}; - calc_mask(packet_in.data, packet_in_data, packet_in_mask); - data_in >> packet_in; - } else { - packet_in_data = 0; - packet_in_mask = 0; - } - - uint16_t cell_number_top = (i / 32) % (2 * FPGA_NBX + 1) * 32 + (i % 32); - - ap_uint<512> top_line = data_cache[cell_number_top]; - ap_uint<32> top_line_mask = mask_cache[cell_number_top]; - - ap_uint diff_sum; - ap_uint diff_sum2; - ap_uint diff_valid; - - ap_uint column_sum = sum_cache[i % 32]; - ap_uint column_sum2 = sum2_cache[i % 32]; - ap_uint column_valid = valid_cache[i % 32]; - - calc_sum(diff_sum, top_line, packet_in_data); - calc_sum2(diff_sum2, top_line, packet_in_data); - calc_mask_diff(diff_valid, top_line_mask, packet_in_mask); - - update_sum(column_sum, diff_sum); - update_sum(column_sum2, diff_sum2); - update_sum(column_valid, diff_valid); - - if (i >= (FPGA_NBX) * 32) { - sum_out << column_sum; - sum2_out << column_sum2; - valid_out << column_valid; - } - - sum_cache[i % 32] = column_sum; - sum2_cache[i % 32] = column_sum2; - valid_cache[i % 32] = column_valid; - - data_cache[cell_number_top] = packet_in_data; - mask_cache[cell_number_top] = packet_in_mask; - } - } - data_out << spot_finder_packet{.data=0, .user=1}; -} - -void spot_finder_line_sum(hls::stream &data_in, - hls::stream &data_out, - hls::stream> &sum_in, - hls::stream> &sum2_in, - hls::stream> &valid_in, - hls::stream> &sum_out, - hls::stream> &sum2_out, - hls::stream> &valid_out) { - spot_finder_packet packet_in; - data_in >> packet_in; - data_out << packet_in; - - ap_uint column_sum_val_save = 0; - ap_uint column_sum2_val_save = 0; - ap_uint column_valid_val_save = 0; - - data_in >> packet_in; - while (!packet_in.user) { - - ap_uint column_sum = 0; - ap_uint column_sum2 = 0; - ap_uint column_valid = 0; - - ap_uint line_sum; - ap_uint line_sum2; - ap_uint line_valid; - -#pragma HLS PIPELINE II=33 - for (int i = 0; i < 32; i++) { - - data_out << packet_in; - data_in >> packet_in; - - sum_in >> column_sum; - sum2_in >> column_sum2; - valid_in >> column_valid; - - sum_out << prefix_sum((column_sum, column_sum_val_save)); - sum2_out << prefix_sum((column_sum2, column_sum2_val_save)); - valid_out << prefix_sum((column_valid, column_valid_val_save)); - - column_sum_val_save = column_sum(SUM_BITWIDTH * 32 - 1, SUM_BITWIDTH * (32 - 2 * FPGA_NBX)); - column_sum2_val_save = column_sum2(SUM2_BITWIDTH * 32 - 1, SUM2_BITWIDTH * (32 - 2 * FPGA_NBX)); - column_valid_val_save = column_valid(MASK_SUM_BITWIDTH * 32 - 1, MASK_SUM_BITWIDTH * (32 - 2 * FPGA_NBX)); - } - - sum_out << prefix_sum((ap_uint(0), column_sum_val_save)); - sum2_out << prefix_sum((ap_uint(0), column_sum2_val_save)); - valid_out << prefix_sum((ap_uint(0), column_valid_val_save)); - - column_sum_val_save = 0; - column_sum2_val_save = 0; - column_valid_val_save = 0; - } - data_out << packet_in; -} - -void spot_finder_line_sum_align(hls::stream &data_in, - hls::stream &data_out, - hls::stream> &sum_in, - hls::stream> &sum2_in, - hls::stream> &valid_in, - hls::stream> &sum_out, - hls::stream> &sum2_out, - hls::stream> &valid_out) { - spot_finder_packet packet_in; - data_in >> packet_in; - data_out << packet_in; - - data_in >> packet_in; - while (!packet_in.user) { -#pragma HLS PIPELINE II=33 - - ap_uint line_sum_val_save = 0; - ap_uint line_sum2_val_save = 0; - ap_uint line_valid_val_save = 0; - - ap_uint line_sum = 0; - ap_uint line_sum2 = 0; - ap_uint line_valid = 0; - - sum_in >> line_sum; - sum2_in >> line_sum2; - valid_in >> line_valid; - - line_sum_val_save = line_sum(SUM_BITWIDTH * 32 - 1, SUM_BITWIDTH * FPGA_NBX); - line_sum2_val_save = line_sum2(SUM2_BITWIDTH * 32 - 1, SUM2_BITWIDTH * FPGA_NBX); - line_valid_val_save = line_valid(MASK_SUM_BITWIDTH * 32 - 1, MASK_SUM_BITWIDTH * FPGA_NBX); - - for (int i = 0; i < 32; i++) { - - data_out << packet_in; - data_in >> packet_in; - - sum_in >> line_sum; - sum2_in >> line_sum2; - valid_in >> line_valid; - - sum_out << (line_sum(SUM_BITWIDTH * FPGA_NBX - 1, 0), line_sum_val_save); - sum2_out << (line_sum2(SUM2_BITWIDTH * FPGA_NBX - 1, 0), line_sum2_val_save); - valid_out << (line_valid(MASK_SUM_BITWIDTH * FPGA_NBX - 1, 0), line_valid_val_save); - - line_sum_val_save = line_sum(SUM_BITWIDTH * 32 - 1, SUM_BITWIDTH * FPGA_NBX); - line_sum2_val_save = line_sum2(SUM2_BITWIDTH * 32 - 1, SUM2_BITWIDTH * FPGA_NBX); - line_valid_val_save = line_valid(MASK_SUM_BITWIDTH * 32 - 1, MASK_SUM_BITWIDTH * FPGA_NBX); - } - } - data_out << packet_in; -} - -strong_pixel_threshold_t calculate_threshold(ap_uint<16> &in_snr_threshold) { -#pragma HLS INLINE - ap_uint<16> tmp = in_snr_threshold; - strong_pixel_threshold_t snr_threshold = 0; - for (int i = 0; i < 16; i++) { -#pragma HLS UNROLL - snr_threshold[i] = tmp[i]; - } - return snr_threshold * snr_threshold; -} - ap_uint<32> count_pixels(ap_uint<32> &in) { #pragma HLS INLINE ap_uint<32> ret = 0; @@ -327,109 +10,48 @@ ap_uint<32> count_pixels(ap_uint<32> &in) { return ret; } -void spot_finder_check_threshold(hls::stream &data_in, - STREAM_512 &data_out, - hls::stream> &sum_in, - hls::stream> &sum2_in, - hls::stream> &valid_in, - hls::stream> &strong_pixel_out, - volatile ap_int<16> &in_count_threshold, - volatile ap_uint<16> &in_snr_threshold) { - spot_finder_packet packet_in; - data_in >> packet_in; - data_out << packet_512_t{.data=packet_in.data, .user=0, .last=0}; - ap_uint line_sum = 0; - ap_uint line_sum2 = 0; - ap_uint line_valid = 0; - - data_in >> packet_in; - while (!packet_in.user) { - ap_int<16> count_threshold = in_count_threshold; - ap_uint<16> snr_threshold = in_snr_threshold; - strong_pixel_threshold_t snr_threshold_sq = calculate_threshold(snr_threshold); - uint32_t strong_pixel_count = 0; - - for (int i = 0; i < RAW_MODULE_SIZE * sizeof(uint16_t) / 64; i++) { -#pragma HLS PIPELINE II=1 - data_out << packet_512_t{.data=packet_in.data, .user=0, .last=0}; - sum_in >> line_sum; - sum2_in >> line_sum2; - valid_in >> line_valid; - ap_axiu<32, 1, 1, 1> strong_pixel{.user = 0}; - - strong_pixel.data = check_threshold(packet_in.data, line_sum, line_sum2, line_valid, snr_threshold_sq, count_threshold); - strong_pixel_count += count_pixels(strong_pixel.data); - strong_pixel_out << strong_pixel; - data_in >> packet_in; - } - - // Save parameters used for spot finding + count of - strong_pixel_out << ap_axiu<32, 1, 1, 1>{.data = count_threshold, .user = 0}; - strong_pixel_out << ap_axiu<32, 1, 1, 1>{.data = snr_threshold, .user = 0}; - strong_pixel_out << ap_axiu<32, 1, 1, 1>{.data = strong_pixel_count, .user = 0}; - for (int i = 0; i < 13; i++) - strong_pixel_out << ap_axiu<32, 1, 1, 1>{.data = 0, .user = 0}; - } - strong_pixel_out << ap_axiu<32,1,1,1>{.data = 0, .user = 1}; - data_out << packet_512_t{.data=0, .user=1, .last=1}; -} - void spot_finder(STREAM_512 &data_in, STREAM_512 &data_out, hls::stream> &strong_pixel_out, volatile ap_int<16> &in_photon_count_threshold, volatile ap_uint<16> &in_strong_pixel_threshold) { -#pragma HLS DATAFLOW - #pragma HLS INTERFACE axis port=data_in #pragma HLS INTERFACE axis port=data_out #pragma HLS INTERFACE axis port=strong_pixel_out #pragma HLS INTERFACE ap_none register port=in_photon_count_threshold #pragma HLS INTERFACE ap_none register port=in_strong_pixel_threshold + packet_512_t packet; + data_in >> packet; + data_out << packet; - hls::stream data_stream_0; - hls::stream data_stream_1, data_stream_2; - hls::stream, 16> sum_stream_0; - hls::stream, 8> sum_stream_1, sum_stream_2; - hls::stream, 16> sum2_stream_0; - hls::stream, 8> sum2_stream_1, sum2_stream_2; - hls::stream, 16> valid_stream_0; - hls::stream, 8> valid_stream_1, valid_stream_2; -#pragma HLS bind_storage variable=data_stream_0 type=fifo impl=bram -#pragma HLS bind_storage variable=data_stream_1 type=fifo impl=bram -#pragma HLS bind_storage variable=data_stream_2 type=fifo impl=bram -#pragma HLS bind_storage variable=sum_stream_0 type=fifo impl=bram -#pragma HLS bind_storage variable=sum_stream_1 type=fifo impl=bram -#pragma HLS bind_storage variable=sum_stream_2 type=fifo impl=bram -#pragma HLS bind_storage variable=sum2_stream_0 type=fifo impl=bram -#pragma HLS bind_storage variable=sum2_stream_1 type=fifo impl=bram -#pragma HLS bind_storage variable=sum2_stream_2 type=fifo impl=bram -#pragma HLS bind_storage variable=valid_stream_0 type=fifo impl=bram -#pragma HLS bind_storage variable=valid_stream_1 type=fifo impl=bram -#pragma HLS bind_storage variable=valid_stream_2 type=fifo impl=bram + data_in >> packet; + while (!packet.user) { + ap_int<16> count_threshold = in_photon_count_threshold; + ap_uint<16> snr_threshold = in_strong_pixel_threshold; + ap_uint<32> strong_pixel_count = 0; + for (int i = 0; i < RAW_MODULE_SIZE * sizeof(uint16_t) / 64; i++) { +#pragma HLS PIPELINE II=1 + data_out << packet; + ap_uint<32> strong_pixel = 0; + ap_int<16> data_unpacked[32]; + unpack32(packet.data, data_unpacked); + for (int j = 0; j < 32; j++) { + if (data_unpacked[j] > count_threshold) + strong_pixel[j] = 1; + else + strong_pixel[j] = 0; + } + strong_pixel_out << ap_axiu<32,1,1,1>{.data = strong_pixel, .user = 0}; + strong_pixel_count += count_pixels(strong_pixel); + data_in >> packet; + } + strong_pixel_out << ap_axiu<32,1,1,1>{.data = count_threshold, .user = 0}; + strong_pixel_out << ap_axiu<32,1,1,1>{.data = snr_threshold, .user = 0}; + strong_pixel_out << ap_axiu<32,1,1,1>{.data = strong_pixel_count, .user = 0}; -#ifndef JFJOCH_HLS_NOSYNTH - spot_finder_col_sum(data_in, data_stream_0, sum_stream_0, sum2_stream_0, valid_stream_0); - spot_finder_line_sum(data_stream_0, data_stream_1, - sum_stream_0, sum2_stream_0, valid_stream_0, - sum_stream_1, sum2_stream_1, valid_stream_1); - spot_finder_line_sum_align(data_stream_1, data_stream_2, - sum_stream_1, sum2_stream_1, valid_stream_1, - sum_stream_2, sum2_stream_2, valid_stream_2); - spot_finder_check_threshold(data_stream_2, data_out, sum_stream_2, sum2_stream_2, valid_stream_2, - strong_pixel_out, in_photon_count_threshold, in_strong_pixel_threshold); -#else - std::vector spot_finder_cores; - spot_finder_cores.emplace_back([&] {spot_finder_col_sum(data_in, data_stream_0, sum_stream_0, sum2_stream_0, valid_stream_0);}); - spot_finder_cores.emplace_back([&] {spot_finder_line_sum(data_stream_0, data_stream_1, - sum_stream_0, sum2_stream_0, valid_stream_0, - sum_stream_1, sum2_stream_1, valid_stream_1);}); - spot_finder_cores.emplace_back([&] {spot_finder_line_sum_align(data_stream_1, data_stream_2, - sum_stream_1, sum2_stream_1, valid_stream_1, - sum_stream_2, sum2_stream_2, valid_stream_2);}); - spot_finder_cores.emplace_back([&] {spot_finder_check_threshold(data_stream_2, data_out, sum_stream_2, sum2_stream_2, valid_stream_2, - strong_pixel_out, in_photon_count_threshold, in_strong_pixel_threshold);}); - for (auto &i : spot_finder_cores) - i.join(); -#endif + for (int i = 0; i < 13; i++) + strong_pixel_out << ap_axiu<32,1,1,1>{.data = 0, .user = 0}; + } + strong_pixel_out << ap_axiu<32,1,1,1>{.data = 0, .user = 1}; + data_out << packet; } diff --git a/fpga/hls/spot_finder.h b/fpga/hls/spot_finder.h index 4f52189b..48219263 100644 --- a/fpga/hls/spot_finder.h +++ b/fpga/hls/spot_finder.h @@ -7,113 +7,4 @@ #include "hls_jfjoch.h" -#define FPGA_NBX 5 -#define FPGA_NBX_CEIL_LOG2 7 -#define SUM_BITWIDTH (16+FPGA_NBX_CEIL_LOG2) -#define SUM2_BITWIDTH (16*2+FPGA_NBX_CEIL_LOG2) -#define MASK_SUM_BITWIDTH (FPGA_NBX_CEIL_LOG2+1) - -struct spot_finder_packet { - ap_uint<512> data; - ap_uint<1> user; -}; - -template -void update_sum(ap_uint &ext_val1, const ap_uint ext_val2) { -#pragma HLS PIPELINE II=1 - - ap_int val1[32], val2[32]; - - unpack32(ext_val1, val1); - unpack32(ext_val2, val2); - - for (int i = 0; i < 32; i++) - val1[i] += val2[i]; - - ext_val1 = pack32(val1); -} - -template -ap_uint prefix_sum(const ap_uint ext_column_sum) { -#pragma HLS PIPELINE II=1 - ap_int column_sum[32 + 2 * FPGA_NBX]; - ap_int line_sum[32]; - - for (int i = 0; i < 32 + 2 * FPGA_NBX; i++) - column_sum[i] = ext_column_sum(i * N + (N - 1), i * N); - - ap_int tmp_sum = 0; - - for (int i = 0 ; i < 2 * FPGA_NBX; i++) { - tmp_sum += column_sum[i]; - } - - for (int i = 0; i < 32; i++) { - tmp_sum += column_sum[i + 2 * FPGA_NBX]; - line_sum[i] = tmp_sum; - tmp_sum -= column_sum[i]; - } - - //for (int i = 0; i < 32; i++) { - // line_sum[i] = 0; - // for (int j = 0; j < 2 * FPGA_NBX + 1; j++) - // line_sum[i] += column_sum[i + j]; - //} - - return pack32(line_sum); -} - -void calc_mask_diff(ap_uint &ext_column_valid, - const ap_uint<32> ext_old_value, - const ap_uint<32> ext_new_value); - -void calc_sum2(ap_uint &ext_column_sum2, - const ap_uint<512> ext_old_value, - const ap_uint<512> ext_new_value); - -void calc_sum(ap_uint &ext_column_sum, - const ap_uint<512> ext_old_value, - const ap_uint<512> ext_new_value); - -void calc_mask(const ap_uint<512> &input, ap_uint<512> &output, ap_uint<32> &mask); - -void spot_finder_col_sum(STREAM_512 &data_in, - hls::stream &data_out, - hls::stream> &sum_out, - hls::stream> &sum2_out, - hls::stream> &valid_out); - -void spot_finder_line_sum(hls::stream &data_in, - hls::stream &data_out, - hls::stream> &sum_in, - hls::stream> &sum2_in, - hls::stream> &valid_in, - hls::stream> &sum_out, - hls::stream> &sum2_out, - hls::stream> &valid_out); - -void spot_finder_line_sum_align(hls::stream &data_in, - hls::stream &data_out, - hls::stream> &sum_in, - hls::stream> &sum2_in, - hls::stream> &valid_in, - hls::stream> &sum_out, - hls::stream> &sum2_out, - hls::stream> &valid_out); - -void spot_finder_check_threshold(hls::stream &data_in, - hls::stream> &sum_in, - hls::stream> &sum2_in, - hls::stream> &valid_in, - hls::stream> &strong_pixel_out, - volatile ap_int<16> &in_photon_count_threshold, - volatile ap_uint<16> &in_strong_pixel_threshold); - -ap_uint<32> check_threshold(const ap_uint<512> data_packed, - const ap_uint sum_packed, - const ap_uint sum2_packed, - const ap_uint valid_packed, - strong_pixel_threshold_t strong_pixel_threshold, - ap_int<16> photon_count_threshold); - #endif //JUNGFRAUJOCH_SPOT_FINDER_H diff --git a/tests/FPGASpotFindingUnitTest.cpp b/tests/FPGASpotFindingUnitTest.cpp index a34442ac..abd53b2e 100644 --- a/tests/FPGASpotFindingUnitTest.cpp +++ b/tests/FPGASpotFindingUnitTest.cpp @@ -6,386 +6,6 @@ #include "../fpga/hls/hls_jfjoch.h" #include "../fpga/hls/spot_finder.h" -TEST_CASE("Pack32_Unpack32","[FPGA][SpotFinder]") { - ap_int<16> value[32]; - for (int i = 0; i < 32; i++) - value[i] = i; - - ap_int<512> packed = pack32(value); - ap_int<16> restore[32]; - unpack32(packed, restore); - for (int i = 0; i < 32; i++) { - REQUIRE(value[i] == restore[i]); - } - -} - -TEST_CASE("Pack32_Unpack32_36","[FPGA][SpotFinder]") { - ap_int<36> value[32]; - for (int i = 0; i < 32; i++) - value[i] = i; - - ap_int<36*32> packed = pack32(value); - ap_int<36> restore[32]; - unpack32(packed, restore); - for (int i = 0; i < 32; i++) { - REQUIRE(value[i] == restore[i]); - } -} - -TEST_CASE("FPGA_calc_sum","[FPGA][SpotFinder]") { - ap_int<16> old_value[32]; - ap_int<16> new_value[32]; - - ap_int new_sum[32]; - ap_int new_sum2[32]; - - for (int i = 0; i < 32; i++) { - old_value[i] = i; - new_value[i] = 2; - } - - ap_uint diff_sum; - ap_uint diff_sum2; - - calc_sum(diff_sum, pack32(old_value), pack32(new_value)); - calc_sum2(diff_sum2, pack32(old_value), pack32(new_value)); - unpack32(diff_sum, new_sum); - unpack32(diff_sum2, new_sum2); - - for (int i = 0; i < 32; i++) { - REQUIRE(new_sum[i] == 2-i); - REQUIRE(new_sum2[i] == 4-i*i); - } -} - -TEST_CASE("FPGA_calc_valid","[FPGA][SpotFinder]") { - ap_uint<32> old_mask = UINT32_MAX; - ap_uint<32> new_mask = UINT32_MAX; - - old_mask[15] = 0; - new_mask[13] = 0; - - ap_uint diff_mask; - calc_mask_diff(diff_mask, old_mask, new_mask); - - ap_int diff_mask_32[32]; - unpack32(diff_mask, diff_mask_32); - - REQUIRE(diff_mask_32[0] == 0); - REQUIRE(diff_mask_32[1] == 0); - - REQUIRE(diff_mask_32[13] == -1); - REQUIRE(diff_mask_32[15] == 1); -} - -TEST_CASE("FPGA_calc_mask","[FPGA][SpotFinder]") { - ap_int<16> value_in[32], value_out[32]; - - for (int i = 0; i < 32; i++) - value_in[i] = 154 + i; - - value_in[15] = INT16_MAX; - value_in[0] = INT16_MIN; - value_in[1] = INT16_MIN + 1; - value_in[2] = INT16_MAX - 1; - - ap_uint<512> input = pack32(value_in); - ap_uint<512> output = 0; - ap_uint<32> mask = 0; - - calc_mask(input, output, mask); - - REQUIRE(mask[0] == 0); - REQUIRE(mask[15] == 0); - REQUIRE(mask[1] == 1); - REQUIRE(mask[2] == 1); - REQUIRE(mask[3] == 1); - REQUIRE(mask[4] == 1); - - unpack32(output, value_out); - - REQUIRE(value_out[0] == 0); - REQUIRE(value_out[15] == 0); - REQUIRE(value_out[1] == value_in[1]); - REQUIRE(value_out[2] == value_in[2]); - REQUIRE(value_out[3] == value_in[3]); - REQUIRE(value_out[4] == value_in[4]); -} - -TEST_CASE("FPGA_update_sum" , "[FPGA][SpotFinder]") { - ap_int arr_val1[32], arr_val2[32], arr_out[32]; - - for (int i = 0; i < 32; i++) { - arr_val1[i] = 5 * i; - arr_val2[i] = 3 * i + 2; - } - ap_uint val1 = pack32(arr_val1); - ap_uint val2 = pack32(arr_val2); - update_sum(val1, val2); - unpack32(val1, arr_out); - for (int i = 0; i < 32; i++) - REQUIRE(arr_out[i] == 8 * i + 2); -} - -int sum_consecutive(int x0, int n) { - int ret = 0; - for (int i = 0; i < n; i++) - ret += x0 + i; - return ret; -} - -TEST_CASE("FPGA_prefix_sum" , "[FPGA][SpotFinder]") { - ap_uint<16*(32+2*FPGA_NBX)> input = 0; - for (int i = 0; i < 32+2*FPGA_NBX; i++) - input(i*16+15, i*16) = i; - - auto output = prefix_sum<16>(input); - ap_uint<16> output_unpacked[32]; - unpack32(output, output_unpacked); - REQUIRE(output_unpacked[0] == sum_consecutive(0, 2 * FPGA_NBX + 1)); - REQUIRE(output_unpacked[2] == sum_consecutive(2, 2 * FPGA_NBX + 1)); - REQUIRE(output_unpacked[7] == sum_consecutive(7, 2 * FPGA_NBX + 1)); -} - -bool Isigma_cpu(double val, double sum, double sum2, float threshold) { - double mean = sum / ((2*FPGA_NBX+1) * (2*FPGA_NBX+1)); - double mean2 = sum2 / ((2*FPGA_NBX+1) * (2*FPGA_NBX+1)); - double variance = mean2 - mean * mean; - double sigma = sqrt(variance); - double i_over_sigma = (val - mean) / sigma; - return (i_over_sigma > threshold); -} - -bool Isigma_fpga(ap_int<16> val, ap_int sum, ap_uint sum2, float threshold) { - return check_threshold(val, sum, sum2, (FPGA_NBX *2 + 1) * (FPGA_NBX *2 + 1), - threshold * threshold, -1); -} - -TEST_CASE("FPGA_spot_check_threshold","[FPGA][SpotFinder]") { - std::vector threshold_values = {1.0, 3.0, 6.0}; - - for (auto threshold: threshold_values) { - uint32_t uniform_val = 10; - uint32_t diff = 0; - for (int16_t val = -100; val < INT16_MAX; val++) { - uint32_t sum = val + ((2 * FPGA_NBX + 1) * (2 * FPGA_NBX + 1) - 1) * uniform_val; - uint32_t sum2 = val * val + ((2 * FPGA_NBX + 1) * (2 * FPGA_NBX + 1) - 1) * uniform_val * uniform_val; - bool cpu = Isigma_cpu(val, sum, sum2, threshold); - bool fpga = Isigma_fpga(val, sum, sum2, threshold); - if (cpu != fpga) { - std::cout << "WRONG!!! " << threshold << " " << val << " " << sum << " " << sum2 << " CPU: " << cpu << " FPGA: " << fpga << std::endl; - diff++; - } - } - REQUIRE(diff == 0); - } -} - -TEST_CASE("FPGA_spot_finder_update_sum","[FPGA][SpotFinder]") { - STREAM_512 input; - hls::stream output; - - hls::stream> sum_out; - hls::stream> sum2_out; - hls::stream> valid_out; - - std::vector input_frame(RAW_MODULE_SIZE), output_frame(RAW_MODULE_SIZE); - for (int i = 0; i < RAW_MODULE_SIZE; i++) { - if (i % RAW_MODULE_COLS == 1023) - input_frame[i] = INT16_MIN; - else - input_frame[i] = i % RAW_MODULE_COLS; - } - auto input_frame_512 = (ap_uint<512> *) input_frame.data(); - auto output_frame_512 = (ap_uint<512> *) output_frame.data(); - - input << packet_512_t{.user = 0}; - 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}; - - spot_finder_col_sum(input, output, sum_out, sum2_out, valid_out); - - REQUIRE(input.size() == 0); - - REQUIRE(output.size() == RAW_MODULE_SIZE * sizeof(uint16_t) / 64 + 2); - REQUIRE(sum_out.size() == RAW_MODULE_SIZE * sizeof(uint16_t) / 64); - REQUIRE(sum2_out.size() == RAW_MODULE_SIZE * sizeof(uint16_t) / 64); - REQUIRE(valid_out.size() == RAW_MODULE_SIZE * sizeof(uint16_t) / 64); - - std::vector sum(RAW_MODULE_SIZE); - std::vector sum2(RAW_MODULE_SIZE); - std::vector valid(RAW_MODULE_SIZE); - - for (int i = 0; i < RAW_MODULE_SIZE * sizeof(uint16_t) / 64; i++) { - ap_uint<32 * SUM_BITWIDTH> tmp_sum; - ap_uint<32 * SUM2_BITWIDTH> tmp_sum2; - ap_uint<32 * MASK_SUM_BITWIDTH> tmp_valid; - sum_out >> tmp_sum; - sum2_out >> tmp_sum2; - valid_out >> tmp_valid; - - ap_uint tmp_sum_unpacked[32]; - ap_uint tmp_sum2_unpacked[32]; - ap_uint tmp_valid_unpacked[32]; - unpack32(tmp_sum, tmp_sum_unpacked); - unpack32(tmp_sum2, tmp_sum2_unpacked); - unpack32(tmp_valid, tmp_valid_unpacked); - - for (int j = 0; j < 32; j++) { - sum[i * 32 + j] = tmp_sum_unpacked[j]; - sum2[i * 32 + j] = tmp_sum2_unpacked[j]; - valid[i * 32 + j] = tmp_valid_unpacked[j]; - } - } - - CHECK(sum[1] == (FPGA_NBX+1) * 1); - CHECK(sum[3] == (FPGA_NBX+1) * 3); - CHECK(sum[1023] == 0); - CHECK(sum[1022+200*1024] == (2 * FPGA_NBX+1) * 1022); - - CHECK(sum2[3] == (FPGA_NBX+1) * 3 * 3); - CHECK(sum2[1023] == 0); - CHECK(sum2[1022+200*1024] == (2 * FPGA_NBX+1) * 1022 * 1022); - - CHECK(valid[1] == FPGA_NBX + 1); - CHECK(valid[3] == FPGA_NBX + 1); - CHECK(valid[1023] == 0); - CHECK(valid[1023 + 323*1024] == 0); - - CHECK(valid[1+1024] == FPGA_NBX + 1 + 1); - CHECK(valid[1+1024] == FPGA_NBX + 1 + 1); - CHECK(valid[1+3*1024] == FPGA_NBX + 1 + 3); - CHECK(valid[1+200*1024] == 2 * FPGA_NBX + 1); - - CHECK(valid[1+509*1024] == FPGA_NBX + 1 + 2); - CHECK(valid[1+510*1024] == FPGA_NBX + 1 + 1); - CHECK(valid[1+511*1024] == FPGA_NBX + 1); - - spot_finder_packet packet_out; - output >> packet_out; - for (int i = 0; i < RAW_MODULE_SIZE * sizeof(uint16_t) / 64; i++) { - output >> packet_out; - output_frame_512[i] = packet_out.data; - } - REQUIRE(output_frame == input_frame); -} - -TEST_CASE("FPGA_spot_finder_line_sum","[FPGA][SpotFinder]") { - hls::stream input; - hls::stream stream_0; - hls::stream output; - - hls::stream> sum_in; - hls::stream> sum2_in; - hls::stream> valid_in; - - hls::stream> sum_stream; - hls::stream> sum2_stream; - hls::stream> valid_stream; - - hls::stream> sum_out; - hls::stream> sum2_out; - hls::stream> valid_out; - - ap_int sum_unpacked[32]; - ap_int sum2_unpacked[32]; - ap_int valid_unpacked[32]; - - std::vector input_frame(RAW_MODULE_COLS), output_frame(RAW_MODULE_COLS); - for (int i = 0; i < RAW_MODULE_COLS; i++) { - if (i % RAW_MODULE_COLS == 1023) - input_frame[i] = INT16_MIN; - else - input_frame[i] = i % RAW_MODULE_COLS; - } - auto input_frame_512 = (ap_uint<512> *) input_frame.data(); - auto output_frame_512 = (ap_uint<512> *) output_frame.data(); - - input << spot_finder_packet{.user = 0}; - for (int i = 0; i < 32; i++) - input << spot_finder_packet{.data = input_frame_512[i], .user = 0}; - - input << spot_finder_packet{.user = 1}; - - for (int i = 0; i < 32; i++) { - for (int j = 0; j < 32; j++) { - sum_unpacked[j] = i * 32 + j; - sum2_unpacked[j] = 8934 + (i * 32 + j); - valid_unpacked[j] = 1; - } - sum_in << pack32(sum_unpacked); - sum2_in << pack32(sum2_unpacked); - valid_in << pack32(valid_unpacked); - } - - spot_finder_line_sum(input, stream_0, sum_in, sum2_in, valid_in, sum_stream, sum2_stream, valid_stream); - REQUIRE(input.size() == 0); - - REQUIRE(stream_0.size() == 32 + 2); - REQUIRE(sum_stream.size() == 33); - REQUIRE(sum2_stream.size() == 33); - REQUIRE(valid_stream.size() == 33); - - spot_finder_line_sum_align(stream_0, output, sum_stream, sum2_stream, valid_stream, sum_out, sum2_out, valid_out); - - REQUIRE(stream_0.size() == 0); - - REQUIRE(output.size() == 32 + 2); - REQUIRE(sum_out.size() == 32); - REQUIRE(sum2_out.size() == 32); - REQUIRE(valid_out.size() == 32); - - std::vector sum_output(RAW_MODULE_COLS); - std::vector sum2_output(RAW_MODULE_COLS); - std::vector valid_output(RAW_MODULE_COLS); - - for (int i = 0; i < 32; i++) { - ap_uint<32 * SUM_BITWIDTH> sum_tmp; - sum_out >> sum_tmp; - unpack32(sum_tmp, sum_unpacked); - for (int j = 0; j < 32; j++) - sum_output[i * 32 + j] = sum_unpacked[j]; - - ap_uint<32 * SUM2_BITWIDTH> sum2_tmp; - sum2_out >> sum2_tmp; - unpack32(sum2_tmp, sum2_unpacked); - for (int j = 0; j < 32; j++) - sum2_output[i * 32 + j] = sum2_unpacked[j]; - - ap_uint<32 * MASK_SUM_BITWIDTH> valid_tmp; - valid_out >> valid_tmp; - unpack32(valid_tmp, valid_unpacked); - for (int j = 0; j < 32; j++) - valid_output[i * 32 + j] = valid_unpacked[j]; - } - - CHECK(sum_output[0] == sum_consecutive(0, FPGA_NBX+1)); - CHECK(sum_output[1] == sum_consecutive(0, FPGA_NBX+2)); - CHECK(sum_output[2] == sum_consecutive(0, FPGA_NBX+3)); - CHECK(sum_output[FPGA_NBX] == sum_consecutive(0, FPGA_NBX*2+1)); - CHECK(sum_output[FPGA_NBX+1] == sum_consecutive(1, FPGA_NBX*2+1)); - CHECK(sum_output[FPGA_NBX+5] == sum_consecutive(5, FPGA_NBX*2+1)); - CHECK(sum_output[1023] == sum_consecutive(1023-FPGA_NBX, FPGA_NBX+1)); - - CHECK(sum2_output[0] == sum_consecutive(8934, FPGA_NBX+1)); - - CHECK(valid_output[0] == FPGA_NBX+1); - CHECK(valid_output[1] == FPGA_NBX+2); - - CHECK(valid_output[1022] == FPGA_NBX+2); - CHECK(valid_output[1023] == FPGA_NBX+1); - - spot_finder_packet packet_out; - output >> packet_out; - for (int i = 0; i < 32; i++) { - output >> packet_out; - output_frame_512[i] = packet_out.data; - } -} - TEST_CASE("FPGA_spot_finder_core","[FPGA][SpotFinder]") { STREAM_512 input; STREAM_512 output;