FPGA: Add SNR threshold to spot finder
This commit is contained in:
@@ -91,8 +91,8 @@ module action_config
|
||||
output reg [7:0] nmodules ,
|
||||
output reg [3:0] nstorage_cells ,
|
||||
output wire [31:0] hbm_size_bytes ,
|
||||
output reg[15:0] spot_finder_count_threshold ,
|
||||
output reg[15:0] spot_finder_snr_threshold ,
|
||||
output reg [15:0] spot_finder_count_threshold,
|
||||
output reg [7:0] spot_finder_snr_threshold,
|
||||
|
||||
output reg data_collection_start ,
|
||||
output reg data_collection_cancel ,
|
||||
@@ -523,14 +523,14 @@ always @(posedge clk) begin
|
||||
if (!resetn)
|
||||
spot_finder_snr_threshold <= 0;
|
||||
else if (w_hs && waddr == `ADDR_SPOT_FINDER_SNR_THR)
|
||||
spot_finder_snr_threshold <= (s_axi_WDATA[15:0] & wmask[15:0]) | (spot_finder_snr_threshold & !wmask[3:0]);
|
||||
spot_finder_snr_threshold <= (s_axi_WDATA[7:0] & wmask[7:0]) | (spot_finder_snr_threshold & !wmask[7:0]);
|
||||
end
|
||||
|
||||
always @(posedge clk) begin
|
||||
if (!resetn)
|
||||
spot_finder_count_threshold <= 0;
|
||||
else if (w_hs && waddr == `ADDR_SPOT_FINDER_CNT_THR)
|
||||
spot_finder_count_threshold <= (s_axi_WDATA[15:0] & wmask[15:0]) | (spot_finder_count_threshold & !wmask[3:0]);
|
||||
spot_finder_count_threshold <= (s_axi_WDATA[15:0] & wmask[15:0]) | (spot_finder_count_threshold & !wmask[15:0]);
|
||||
end
|
||||
|
||||
always @ (posedge clk) begin
|
||||
|
||||
@@ -231,7 +231,7 @@ void spot_finder(STREAM_512 &data_in,
|
||||
STREAM_512 &data_out,
|
||||
hls::stream<ap_axiu<32,1,1,1>> &strong_pixel_out,
|
||||
volatile ap_int<16> &in_count_threshold,
|
||||
volatile ap_uint<16> &in_snr_threshold);
|
||||
volatile ap_uint<8> &in_snr_threshold);
|
||||
|
||||
void bitshuffle(STREAM_512 &data_in,
|
||||
STREAM_512 &data_out);
|
||||
|
||||
@@ -2,6 +2,14 @@
|
||||
|
||||
#include "hls_jfjoch.h"
|
||||
|
||||
#define SUM_BITWIDTH 28 // 16 + 11 + 1
|
||||
#define SUM2_BITWIDTH 44 // 32 + 11 + 1
|
||||
#define VALID_BITWIDTH 11 // 11
|
||||
|
||||
#ifdef JFJOCH_HLS_NOSYNTH
|
||||
#include <thread>
|
||||
#endif
|
||||
|
||||
ap_uint<32> count_pixels(ap_uint<32> &in) {
|
||||
#pragma HLS INLINE
|
||||
ap_uint<32> ret = 0;
|
||||
@@ -10,40 +18,196 @@ ap_uint<32> count_pixels(ap_uint<32> &in) {
|
||||
return ret;
|
||||
}
|
||||
|
||||
void spot_finder(STREAM_512 &data_in,
|
||||
STREAM_512 &data_out,
|
||||
hls::stream<ap_axiu<32,1,1,1>> &strong_pixel_out,
|
||||
volatile ap_int<16> &in_count_threshold,
|
||||
volatile ap_uint<16> &in_snr_threshold) {
|
||||
#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_count_threshold
|
||||
#pragma HLS INTERFACE ap_none register port=in_snr_threshold
|
||||
packet_512_t packet;
|
||||
struct spot_finder_packet {
|
||||
ap_uint<512> data;
|
||||
ap_uint<1> user;
|
||||
ap_uint<1> last;
|
||||
};
|
||||
|
||||
void spot_finder_in_stream(STREAM_512 &data_in,
|
||||
hls::stream<spot_finder_packet> &data_out) {
|
||||
packet_512_t packet_in;
|
||||
data_in >> packet_in;
|
||||
data_out << spot_finder_packet{.data = packet_in.data, .user = packet_in.user, .last = packet_in.last};
|
||||
data_in >> packet_in;
|
||||
while (!packet_in.user) {
|
||||
#pragma HLS PIPELINE II=1
|
||||
data_out << spot_finder_packet{.data = packet_in.data, .user = packet_in.user, .last = packet_in.last};
|
||||
data_in >> packet_in;
|
||||
}
|
||||
data_out << spot_finder_packet{.data = packet_in.data, .user = packet_in.user, .last = packet_in.last};
|
||||
}
|
||||
|
||||
ap_uint<32> calc_mask(ap_int<16> val[32]) {
|
||||
ap_uint<32> ret = 0;
|
||||
for (int i = 0; i < 32; i++) {
|
||||
if ((val[i] == INT16_MAX) || (val[i] == INT16_MIN))
|
||||
ret[i] = 0;
|
||||
else
|
||||
ret[i] = 1;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
ap_int<SUM_BITWIDTH> calc_sum(ap_int<16> val[32], ap_uint<32> mask) {
|
||||
#pragma HLS PIPELINE II=1
|
||||
ap_int<SUM_BITWIDTH> ret = 0;
|
||||
for (int i = 0; i < 32; i++) {
|
||||
if (mask[i])
|
||||
ret += val[i];
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
ap_int<SUM2_BITWIDTH> calc_sum2(ap_int<16> val[32], ap_uint<32> mask) {
|
||||
#pragma HLS PIPELINE II=1
|
||||
ap_int<SUM2_BITWIDTH> ret = 0;
|
||||
for (int i = 0; i < 32; i++) {
|
||||
if (mask[i])
|
||||
ret += val[i] * val[i];
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
ap_int<VALID_BITWIDTH> calc_valid(ap_uint<32> mask) {
|
||||
#pragma HLS PIPELINE II=1
|
||||
ap_int<VALID_BITWIDTH> ret = 0;
|
||||
for (int i = 0; i < 32; i++) {
|
||||
ret += mask[i];
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
void spot_finder_prepare(hls::stream<spot_finder_packet> &data_in,
|
||||
hls::stream<spot_finder_packet> &data_out,
|
||||
hls::stream<ap_int<SUM_BITWIDTH>> &sum_out,
|
||||
hls::stream<ap_int<SUM2_BITWIDTH>> &sum2_out,
|
||||
hls::stream<ap_int<VALID_BITWIDTH>> &valid_out) {
|
||||
spot_finder_packet packet;
|
||||
data_in >> packet;
|
||||
data_out << packet;
|
||||
|
||||
ap_int<SUM_BITWIDTH> sum[32];
|
||||
ap_int<SUM2_BITWIDTH> sum2[32];
|
||||
ap_int<VALID_BITWIDTH> valid[32];
|
||||
|
||||
for (int col = 0; col < 32; col++) {
|
||||
sum[col] = 0;
|
||||
sum2[col] = 0;
|
||||
valid[col] = 0;
|
||||
}
|
||||
|
||||
data_in >> packet;
|
||||
while (!packet.user) {
|
||||
ap_int<16> count_threshold = in_count_threshold;
|
||||
ap_uint<16> snr_threshold = in_snr_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;
|
||||
ap_int<16> val[32];
|
||||
unpack32(packet.data, val);
|
||||
ap_uint<32> mask = calc_mask(val);
|
||||
|
||||
if ((i / 32) % 32 == 0) {
|
||||
sum[i % 32] = calc_sum(val, mask);
|
||||
sum2[i % 32] = calc_sum2(val, mask);
|
||||
valid[i % 32] = calc_valid(mask);
|
||||
} else if ((i / 32) % 32 == 31) {
|
||||
sum_out << sum[i % 32] + calc_sum(val, mask);
|
||||
sum2_out << sum2[i % 32] + calc_sum2(val, mask);
|
||||
valid_out << valid[i % 32] + calc_valid(mask);
|
||||
} else {
|
||||
sum[i % 32] += calc_sum(val, mask);
|
||||
sum2[i % 32] += calc_sum2(val, mask);
|
||||
valid[i % 32] += calc_valid(mask);
|
||||
}
|
||||
|
||||
data_in >> packet;
|
||||
}
|
||||
}
|
||||
data_out << packet;
|
||||
}
|
||||
|
||||
ap_uint<32> spot_finder_snr_threshold(ap_int<16> val[32],
|
||||
ap_uint<8> snr_threshold,
|
||||
ap_int<SUM_BITWIDTH> sum,
|
||||
ap_int<SUM2_BITWIDTH> sum2,
|
||||
ap_int<VALID_BITWIDTH> valid_count) {
|
||||
#pragma HLS PIPELINE II=1
|
||||
if (snr_threshold == 0)
|
||||
return UINT32_MAX;
|
||||
|
||||
ap_int<SUM2_BITWIDTH+11> variance = valid_count * sum2 - sum * sum;
|
||||
ap_int<SUM2_BITWIDTH+11+11+8-2> threshold = (variance * snr_threshold * valid_count + 2) / 4;
|
||||
// snr_threshold is in units of 0.25
|
||||
|
||||
ap_uint<32> ret = 0;
|
||||
for (int j = 0; j < 32; j++) {
|
||||
ap_int<SUM_BITWIDTH+1> in_minus_mean = val[j] * valid_count - sum;
|
||||
if ((in_minus_mean * in_minus_mean * (valid_count - 1) > threshold) &&
|
||||
(in_minus_mean > 0))
|
||||
ret[j] = 1;
|
||||
else
|
||||
ret[j] = 0;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
ap_uint<32> spot_finder_count_threshold(ap_int<16> val[32],
|
||||
ap_int<16> &count_threshold) {
|
||||
#pragma HLS PIPELINE II=1
|
||||
if (count_threshold <= 0)
|
||||
return UINT32_MAX;
|
||||
ap_uint<32> ret = 0;
|
||||
for (int j = 0; j < 32; j++) {
|
||||
if (val[j] >= count_threshold)
|
||||
ret[j] = 1;
|
||||
else
|
||||
ret[j] = 0;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
void spot_finder_apply_threshold(hls::stream<spot_finder_packet> &data_in,
|
||||
STREAM_512 &data_out,
|
||||
hls::stream<ap_int<SUM_BITWIDTH>> &sum_in,
|
||||
hls::stream<ap_int<SUM2_BITWIDTH>> &sum2_in,
|
||||
hls::stream<ap_int<VALID_BITWIDTH>> &valid_in,
|
||||
hls::stream<ap_axiu<32,1,1,1>> &strong_pixel_out,
|
||||
volatile ap_int<16> &in_count_threshold,
|
||||
volatile ap_uint<8> &in_snr_threshold) {
|
||||
spot_finder_packet packet_in;
|
||||
|
||||
data_in >> packet_in;
|
||||
data_out << packet_512_t{.data = packet_in.data, .user = packet_in.user, .last = packet_in.last};
|
||||
|
||||
ap_int<SUM_BITWIDTH> sum[32];
|
||||
ap_int<SUM2_BITWIDTH> sum2[32];
|
||||
ap_int<VALID_BITWIDTH> valid[32];
|
||||
|
||||
data_in >> packet_in;
|
||||
while (!packet_in.user) {
|
||||
ap_int<16> count_threshold = in_count_threshold;
|
||||
ap_uint<8> snr_threshold = in_snr_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
|
||||
|
||||
if ((i / 32) % 32 == 0) {
|
||||
sum_in >> sum[i % 32];
|
||||
sum2_in >> sum2[i % 32];
|
||||
valid_in >> valid[i % 32];
|
||||
}
|
||||
|
||||
data_out << packet_512_t{.data = packet_in.data, .user = packet_in.user, .last = packet_in.last};
|
||||
ap_int<16> data_unpacked[32];
|
||||
unpack32(packet_in.data, data_unpacked);
|
||||
|
||||
ap_uint<32> strong_pixel = spot_finder_count_threshold(data_unpacked, count_threshold) &
|
||||
spot_finder_snr_threshold(data_unpacked, snr_threshold,
|
||||
sum[i % 32], sum2[i % 32], valid[i % 32]);
|
||||
|
||||
strong_pixel_out << ap_axiu<32,1,1,1>{.data = strong_pixel, .user = 0};
|
||||
strong_pixel_count += count_pixels(strong_pixel);
|
||||
data_in >> packet;
|
||||
data_in >> packet_in;
|
||||
}
|
||||
|
||||
// Save module statistics
|
||||
@@ -55,5 +219,42 @@ void spot_finder(STREAM_512 &data_in,
|
||||
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;
|
||||
data_out << packet_512_t{.data = packet_in.data, .user = packet_in.user, .last = packet_in.last};
|
||||
}
|
||||
|
||||
|
||||
void spot_finder(STREAM_512 &data_in,
|
||||
STREAM_512 &data_out,
|
||||
hls::stream<ap_axiu<32,1,1,1>> &strong_pixel_out,
|
||||
volatile ap_int<16> &in_count_threshold,
|
||||
volatile ap_uint<8> &in_snr_threshold) {
|
||||
#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_count_threshold
|
||||
#pragma HLS INTERFACE ap_none register port=in_snr_threshold
|
||||
#pragma HLS DATAFLOW
|
||||
|
||||
hls::stream<spot_finder_packet, 2> data_0;
|
||||
hls::stream<spot_finder_packet, 2048> data_1;
|
||||
#pragma HLS BIND_STORAGE variable=data_1 type=fifo impl=uram
|
||||
hls::stream<ap_int<SUM_BITWIDTH>, 64> sum_0;
|
||||
hls::stream<ap_int<SUM2_BITWIDTH>, 64> sum2_0;
|
||||
hls::stream<ap_int<VALID_BITWIDTH>, 64> valid_0;
|
||||
#ifndef JFJOCH_HLS_NOSYNTH
|
||||
spot_finder_in_stream(data_in, data_0);
|
||||
spot_finder_prepare(data_0, data_1, sum_0, sum2_0, valid_0);
|
||||
spot_finder_apply_threshold(data_1, data_out, sum_0, sum2_0, valid_0, strong_pixel_out,
|
||||
in_count_threshold, in_snr_threshold);
|
||||
#else
|
||||
std::vector<std::thread> spot_finder_cores;
|
||||
spot_finder_cores.emplace_back([&] {spot_finder_in_stream(data_in, data_0);});
|
||||
spot_finder_cores.emplace_back([&] {spot_finder_prepare(data_0, data_1, sum_0, sum2_0, valid_0);});
|
||||
spot_finder_cores.emplace_back([&] {spot_finder_apply_threshold(data_1, data_out, sum_0, sum2_0, valid_0,
|
||||
strong_pixel_out, in_count_threshold,
|
||||
in_snr_threshold);});
|
||||
for (auto &i : spot_finder_cores)
|
||||
i.join();
|
||||
|
||||
#endif
|
||||
}
|
||||
|
||||
@@ -19,7 +19,7 @@ class HLSSimulatedDevice : public FPGAAcquisitionDevice {
|
||||
AXI_STREAM dout_eth;
|
||||
|
||||
ap_int<16> count_threshold = INT16_MAX;
|
||||
ap_uint<16> snr_threshold = 0;
|
||||
ap_uint<8> snr_threshold = 0;
|
||||
|
||||
DataCollectionConfig cfg;
|
||||
|
||||
|
||||
@@ -11,7 +11,7 @@ TEST_CASE("FPGA_spot_finder_core","[FPGA][SpotFinder]") {
|
||||
hls::stream<ap_axiu<32,1,1,1>> strong_pixel;
|
||||
|
||||
ap_int<16> in_photon_count_threshold = 8;
|
||||
ap_uint<16> in_strong_pixel_threshold = 16;
|
||||
ap_uint<8> in_strong_pixel_threshold = 16;
|
||||
|
||||
std::vector<int16_t> input_frame(RAW_MODULE_SIZE), output_frame(RAW_MODULE_SIZE);
|
||||
for (int i = 0; i < RAW_MODULE_SIZE; i++) {
|
||||
|
||||
Reference in New Issue
Block a user