170 lines
6.7 KiB
C++
170 lines
6.7 KiB
C++
// SPDX-FileCopyrightText: 2024 Filip Leonarski, Paul Scherrer Institute <filip.leonarski@psi.ch>
|
|
// 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<ap_uint<UDP_METADATA_STREAM_WIDTH> > &udp_metadata_in,
|
|
AXI_STREAM &data_out,
|
|
hls::stream<axis_addr> &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_STREAM_WIDTH> 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;
|
|
}
|
|
|