// SPDX-FileCopyrightText: 2024 Filip Leonarski, Paul Scherrer Institute // SPDX-License-Identifier: CERN-OHL-S-2.0 #include "hls_jfjoch.h" #include "../hls_simulation/sls_packet.h" void sls_detector(AXI_STREAM &udp_payload_in, hls::stream > &udp_metadata_in, AXI_STREAM &data_out, hls::stream &addr_out, uint64_t& counter, uint32_t& counter_eth_error, uint32_t& counter_len_error, uint64_t& pulse_id, ap_uint<4> data_stream, volatile ap_uint<1> &in_clear_counters, volatile ap_uint<1> &idle) { #pragma HLS INTERFACE ap_ctrl_none port=return #pragma HLS INTERFACE axis register both port=udp_payload_in #pragma HLS INTERFACE axis register both port=data_out #pragma HLS INTERFACE axis register both port=udp_metadata_in #pragma HLS INTERFACE axis register both port=addr_out #pragma HLS INTERFACE ap_vld register port=pulse_id #pragma HLS INTERFACE ap_vld register port=counter #pragma HLS INTERFACE ap_vld register port=counter_eth_error #pragma HLS INTERFACE ap_vld register port=counter_len_error #pragma HLS INTERFACE ap_none register port=in_clear_counters #pragma HLS INTERFACE ap_none register port=idle #pragma HLS INTERFACE ap_none register port=data_stream #pragma HLS pipeline II=1 style=flp enum sls_detector_state {INSPECT_HEADER, FORWARD, DISCARD}; static sls_detector_state state = INSPECT_HEADER; static ap_uint<128> reminder = 0; packet_512_t packet_in; packet_512_t packet_out; packet_out.user = 0; packet_out.dest = 0; packet_out.id = 0; ap_uint udp_metadata; static ap_uint<8> beat_counter; static ap_uint<8> packet_length = 0; static uint64_t internal_counter = 0; static uint32_t internal_counter_eth_error = 0; static uint32_t internal_counter_len_error = 0; static uint64_t internal_pulseid = UINT64_MAX; if ( in_clear_counters.read()) { internal_counter = 0; internal_counter_len_error = 0; internal_counter_eth_error = 0; } #pragma HLS RESET variable=internal_counter #pragma HLS RESET variable=internal_counter_eth_error #pragma HLS RESET variable=internal_counter_len_error #pragma HLS RESET variable=internal_pulseid #pragma HLS RESET variable=state if (state == INSPECT_HEADER && udp_metadata_in.empty()) { counter = internal_counter; counter_eth_error = internal_counter_eth_error; counter_len_error = internal_counter_len_error; pulse_id = internal_pulseid; return; } ap_uint<16> udp_dest_port = 0; ap_uint<4> udp_data_stream = 0; if (udp_payload_in.read_nb(packet_in)) { switch (state) { case INSPECT_HEADER: udp_metadata_in >> udp_metadata; udp_dest_port = udp_metadata_dest_port(udp_metadata); udp_data_stream = udp_dest_port(11, 8); if ((udp_metadata_payload_size(udp_metadata) == sizeof(bunchid_payload)) && (udp_metadata_eth_err(udp_metadata) == 0) && (udp_metadata_len_err(udp_metadata) == 0) && (packet_in.last) && (packet_in.data(6*8 + 31, 6*8) == BUNCHID_MAGICN) && (packet_in.data(6*8 + 2 * 32 + 31, 6*8 + 2 * 32) == BUNCHID_MAGICN)) { internal_pulseid = (packet_in.data(6 * 8 + 5 * 32 + 31, 6 * 8 + 5 * 32), packet_in.data(6*8 + 3 * 32 + 31, 6 * 8 + 3 * 32)); } else if ((udp_metadata_eth_err(udp_metadata) == 0) && (udp_metadata_len_err(udp_metadata) == 0) && (data_stream == udp_data_stream) && (packet_in.data(63, 0) != 0)) { ap_uint<16> row = packet_in.data(4 * 64 + 31, 4 * 64 + 16); ap_uint<16> column = packet_in.data(4 * 64 + 47, 4 * 64 + 32); ap_uint<8> detector_type = packet_in.data(5*64+48+7, 5*64+48); axis_addr addr; addr.eth_packet = packet_in.data(96+8, 96); addr.column = column[0]; addr.row = udp_dest_port[0]; addr.det_type = detector_type; if ((detector_type == SLS_DETECTOR_TYPE_JUNGFRAU) && (udp_metadata_payload_size(udp_metadata) == sizeof(jf_udp_payload))) { packet_length = 128; } else if ((detector_type == SLS_DETECTOR_TYPE_EIGER) && (udp_metadata_payload_size(udp_metadata) == sizeof(eiger_udp_payload))) { packet_length = 64; } else { state = DISCARD; break; } beat_counter = 0; reminder = packet_in.data(511, 384); addr.frame_number = packet_in.data(63, 0) - 1; // Calculate frame_number from zero addr.debug = packet_in.data(5 * 64 + 31, 5 * 64); addr.timestamp = packet_in.data(3 * 64 + 63, 3 * 64); addr.bunchid = packet_in.data(2 * 64 + 63, 2 * 64); addr.module = udp_dest_port(5,1); addr.detector_type = detector_type; addr.exptime = packet_in.data(95, 64); addr.packet_length = packet_length; addr.last = 0; addr_out << addr; state = FORWARD; internal_counter++; } else { if (udp_metadata_eth_err(udp_metadata)) internal_counter_eth_error++; else if (udp_metadata_len_err(udp_metadata)) internal_counter_len_error++; state = DISCARD; } break; case FORWARD: packet_out.last = (beat_counter == packet_length - 1); packet_out.data = (packet_in.data(383, 0), reminder); data_out << packet_out; reminder = packet_in.data(511, 384); beat_counter++; break; case DISCARD: break; } if (packet_in.last) state = INSPECT_HEADER; } counter = internal_counter; counter_eth_error = internal_counter_eth_error; counter_len_error = internal_counter_len_error; pulse_id = internal_pulseid; if (state == INSPECT_HEADER) idle = 1; else idle = 0; }