265 lines
11 KiB
C++
265 lines
11 KiB
C++
// Copyright (2019-2023) Paul Scherrer Institute
|
|
|
|
#include "hls_jfjoch.h"
|
|
#include "ip_header_checksum.h"
|
|
|
|
void generate_packet_jungfrau(STREAM_512 &data_out,
|
|
ap_uint<256> *d_hbm_p0,
|
|
ap_uint<256> *d_hbm_p1,
|
|
ap_uint<32> hbm_size_bytes,
|
|
ap_uint<32> frame,
|
|
ap_uint<10> mem_cell,
|
|
ap_uint<8> module,
|
|
ap_uint<7> eth_packet,
|
|
ap_uint<48> src_mac_addr,
|
|
ap_uint<48> dest_mac_addr,
|
|
ap_uint<32> src_ipv4_addr,
|
|
ap_uint<32> dest_ipv4_addr,
|
|
ap_uint<64> bunchid,
|
|
ap_uint<32> exptime,
|
|
ap_uint<64> timestamp,
|
|
ap_uint<32> debug,
|
|
ap_uint<1> user = 0) {
|
|
#pragma HLS PIPELINE II=130
|
|
ap_uint<720> header = 0;
|
|
|
|
header(47 , 0) = dest_mac_addr;
|
|
header(95 , 48) = src_mac_addr;
|
|
header(111, 96) = 0x0008; // ETHER_IP = IPv4
|
|
header(eth_payload_pos+3 , eth_payload_pos ) = 0x5; // header len of 5
|
|
header(eth_payload_pos+7 , eth_payload_pos+4 ) = 0x4; // IPv4
|
|
header(eth_payload_pos+31 , eth_payload_pos+16 ) = 0x4C20; // total length = 8268
|
|
header(eth_payload_pos+79 , eth_payload_pos+72 ) = PROTOCOL_UDP; // UDP
|
|
header(eth_payload_pos+127, eth_payload_pos+96 ) = src_ipv4_addr;
|
|
header(eth_payload_pos+159, eth_payload_pos+128) = dest_ipv4_addr;
|
|
header(eth_payload_pos+95 , eth_payload_pos+80 ) = computeCheckSum20B(header(eth_payload_pos + 159, eth_payload_pos));
|
|
|
|
header(ipv4_payload_pos+47, ipv4_payload_pos+32) = 0x3820; // UDP length = 8248
|
|
header(udp_payload_pos+63, udp_payload_pos) = frame + 1;
|
|
header(udp_payload_pos+95, udp_payload_pos+64) = exptime;
|
|
header(udp_payload_pos+127, udp_payload_pos+96) = eth_packet;
|
|
header(udp_payload_pos+2*64+63, udp_payload_pos+2*64) = bunchid;
|
|
header(udp_payload_pos+3*64+63, udp_payload_pos+3*64) = timestamp;
|
|
header(udp_payload_pos+4*64+31, udp_payload_pos+4*64+16) = 2 * module;
|
|
header(udp_payload_pos+5*64+31, udp_payload_pos+5*64) = debug;
|
|
header(udp_payload_pos+5*64+55, udp_payload_pos+5*64+48) = SLS_DETECTOR_TYPE_JUNGFRAU;
|
|
|
|
packet_512_t packet;
|
|
packet.data = header(511 ,0);
|
|
packet.last = 0;
|
|
packet.dest = 0;
|
|
packet.id = 0;
|
|
packet.strb = UINT64_MAX;
|
|
packet.keep = UINT64_MAX;
|
|
packet.user = user;
|
|
|
|
data_out << packet;
|
|
|
|
ap_uint<32> offset_hbm_0 = 20 * hbm_size_bytes / 32;
|
|
ap_uint<32> offset_hbm_1 = 21 * hbm_size_bytes / 32;
|
|
|
|
ap_uint<208> remainder = header(719, 512);
|
|
for (int i = 0; i < 128; i++) {
|
|
ap_uint<512> tmp;
|
|
tmp(255, 0) = d_hbm_p0[offset_hbm_0 + mem_cell * 128 * 128 + eth_packet * 128 + i];
|
|
tmp(511, 256) = d_hbm_p1[offset_hbm_1 + mem_cell * 128 * 128 + eth_packet * 128 + i];
|
|
|
|
packet.data(207, 0) = remainder;
|
|
packet.data(511, 208) = tmp(303, 0);
|
|
data_out << packet;
|
|
remainder = tmp(511, 304);
|
|
}
|
|
packet.data(207, 0) = remainder;
|
|
packet.data(511, 208) = 0;
|
|
packet.keep(63, 26) = 0;
|
|
packet.last = 1;
|
|
data_out << packet;
|
|
}
|
|
|
|
void generate_packet_eiger(STREAM_512 &data_out,
|
|
ap_uint<256> *d_hbm_p0,
|
|
ap_uint<256> *d_hbm_p1,
|
|
ap_uint<32> hbm_size_bytes,
|
|
ap_uint<32> frame,
|
|
ap_uint<10> mem_cell,
|
|
ap_uint<8> module,
|
|
ap_uint<8> eth_packet,
|
|
ap_uint<48> src_mac_addr,
|
|
ap_uint<48> dest_mac_addr,
|
|
ap_uint<32> src_ipv4_addr,
|
|
ap_uint<32> dest_ipv4_addr,
|
|
ap_uint<32> exptime,
|
|
ap_uint<64> timestamp,
|
|
ap_uint<32> debug,
|
|
ap_uint<1> user = 0) {
|
|
#pragma HLS PIPELINE II=66
|
|
ap_uint<720> header = 0;
|
|
|
|
header(47 , 0) = dest_mac_addr;
|
|
header(95 , 48) = src_mac_addr;
|
|
header(111, 96) = 0x0008; // ETHER_IP = IPv4
|
|
header(eth_payload_pos+3 , eth_payload_pos ) = 0x5; // header len of 5
|
|
header(eth_payload_pos+7 , eth_payload_pos+4 ) = 0x4; // IPv4
|
|
header(eth_payload_pos+31 , eth_payload_pos+16 ) = 0x4C10; // total length = 4172
|
|
header(eth_payload_pos+79 , eth_payload_pos+72 ) = PROTOCOL_UDP; // UDP
|
|
header(eth_payload_pos+127, eth_payload_pos+96 ) = src_ipv4_addr;
|
|
header(eth_payload_pos+159, eth_payload_pos+128) = dest_ipv4_addr;
|
|
header(eth_payload_pos+95 , eth_payload_pos+80 ) = computeCheckSum20B(header(eth_payload_pos + 159, eth_payload_pos));
|
|
|
|
header(ipv4_payload_pos+47, ipv4_payload_pos+32) = 0x3810; // UDP length = 4152
|
|
header(udp_payload_pos+63, udp_payload_pos) = frame + 1;
|
|
header(udp_payload_pos+95, udp_payload_pos+64) = exptime;
|
|
header(udp_payload_pos+127, udp_payload_pos+96) = (eth_packet / 2) % 64;
|
|
header(udp_payload_pos+2*64+63, udp_payload_pos+2*64) = 0;
|
|
header(udp_payload_pos+3*64+63, udp_payload_pos+3*64) = timestamp;
|
|
header(udp_payload_pos+4*64+31, udp_payload_pos+4*64+16) = 2 * module + ((eth_packet >= 128) ? 1 : 0);
|
|
|
|
header(udp_payload_pos+4*64+47, udp_payload_pos+4*64+32) = (eth_packet % 2);
|
|
header(udp_payload_pos+5*64+31, udp_payload_pos+5*64) = debug;
|
|
header(udp_payload_pos+5*64+55, udp_payload_pos+5*64+48) = SLS_DETECTOR_TYPE_EIGER;
|
|
|
|
packet_512_t packet;
|
|
packet.data = header(511 ,0);
|
|
packet.last = 0;
|
|
packet.dest = 0;
|
|
packet.id = 0;
|
|
packet.strb = UINT64_MAX;
|
|
packet.keep = UINT64_MAX;
|
|
packet.user = user;
|
|
|
|
data_out << packet;
|
|
|
|
ap_uint<32> offset_hbm_0 = 20 * hbm_size_bytes / 32;
|
|
ap_uint<32> offset_hbm_1 = 21 * hbm_size_bytes / 32;
|
|
|
|
ap_uint<208> remainder = header(719, 512);
|
|
for (int i = 0; i < 64; i++) {
|
|
ap_uint<512> tmp;
|
|
tmp(255, 0) = d_hbm_p0[offset_hbm_0 + mem_cell * 64 * 256 + eth_packet * 64 + i];
|
|
tmp(511, 256) = d_hbm_p1[offset_hbm_1 + mem_cell * 64 * 256 + eth_packet * 64 + i];
|
|
|
|
packet.data(207, 0) = remainder;
|
|
packet.data(511, 208) = tmp(303, 0);
|
|
data_out << packet;
|
|
remainder = tmp(511, 304);
|
|
}
|
|
packet.data(207, 0) = remainder;
|
|
packet.data(511, 208) = 0;
|
|
packet.keep(63, 26) = 0;
|
|
packet.last = 1;
|
|
data_out << packet;
|
|
}
|
|
|
|
int frame_generator(STREAM_512 &data_out,
|
|
ap_uint<256> *d_hbm_p0,
|
|
ap_uint<256> *d_hbm_p1,
|
|
ap_uint<32> hbm_size_bytes,
|
|
ap_uint<48> src_mac_addr,
|
|
ap_uint<32> src_ipv4_addr,
|
|
volatile ap_uint<1> &in_cancel,
|
|
const FrameGeneratorConfig &config) {
|
|
#pragma HLS INTERFACE mode=s_axilite port=return
|
|
#pragma HLS INTERFACE mode=s_axilite port=config
|
|
#pragma HLS INTERFACE mode=ap_none register port=src_mac_addr
|
|
#pragma HLS INTERFACE mode=ap_none register port=src_ipv4_addr
|
|
#pragma HLS INTERFACE mode=ap_none register port=in_cancel
|
|
|
|
#pragma HLS INTERFACE register ap_none port=hbm_size_bytes
|
|
#pragma HLS INTERFACE m_axi port=d_hbm_p0 bundle=d_hbm_p0 depth=512 offset=off \
|
|
max_read_burst_length=16 max_write_burst_length=2 latency=120 num_write_outstanding=2 num_read_outstanding=9
|
|
#pragma HLS INTERFACE m_axi port=d_hbm_p1 bundle=d_hbm_p1 depth=512 offset=off \
|
|
max_read_burst_length=16 max_write_burst_length=2 latency=120 num_write_outstanding=2 num_read_outstanding=9
|
|
|
|
#pragma HLS INTERFACE register both axis port=data_out
|
|
|
|
if ((config.modules > MAX_MODULES_FPGA) || (config.modules == 0))
|
|
return 1;
|
|
|
|
if ((config.detector_type != SLS_DETECTOR_TYPE_EIGER)
|
|
&& (config.detector_type != SLS_DETECTOR_TYPE_JUNGFRAU))
|
|
return 2;
|
|
|
|
if (config.frames == 0)
|
|
return 0;
|
|
|
|
if (config.modules * (config.images_in_memory + 1) >= hbm_size_bytes * 2 / (RAW_MODULE_SIZE * sizeof(uint16_t)))
|
|
return 3;
|
|
|
|
union {
|
|
uint64_t u64;
|
|
double d;
|
|
} pulse_id_conv;
|
|
pulse_id_conv.d = config.pulse_id;
|
|
|
|
// send one packet with TUSER = 1, to reset on network cores on the way
|
|
generate_packet_jungfrau(data_out,
|
|
d_hbm_p0,
|
|
d_hbm_p1,
|
|
hbm_size_bytes,
|
|
0, 0, 0, 0,
|
|
src_mac_addr,
|
|
config.dest_mac_addr,
|
|
src_ipv4_addr,
|
|
config.dest_ipv4_addr,
|
|
pulse_id_conv.u64,
|
|
config.exptime,
|
|
config.exptime,
|
|
config.debug, 1);
|
|
|
|
ap_uint<7> frame_cell = 0;
|
|
for (uint32_t f = 0; f < config.frames; f++) {
|
|
ap_uint<1> local_cancel = in_cancel;
|
|
if (local_cancel == 1)
|
|
break;
|
|
if (config.detector_type == SLS_DETECTOR_TYPE_JUNGFRAU) {
|
|
generate_jf_frame:
|
|
for (uint32_t m = 0; m < config.modules; m++) {
|
|
generate_jf_packet:
|
|
for (uint32_t p = 0; p < 128; p++) {
|
|
generate_packet_jungfrau(data_out,
|
|
d_hbm_p0,
|
|
d_hbm_p1,
|
|
hbm_size_bytes,
|
|
f, frame_cell * config.modules + m,
|
|
m, p,
|
|
src_mac_addr,
|
|
config.dest_mac_addr,
|
|
src_ipv4_addr,
|
|
config.dest_ipv4_addr,
|
|
pulse_id_conv.u64,
|
|
config.exptime,
|
|
config.exptime * f,
|
|
config.debug, 0);
|
|
}
|
|
}
|
|
} else {
|
|
generate_eiger_frame:
|
|
for (uint32_t m = 0; m < config.modules; m++) {
|
|
generate_eiger_packet:
|
|
for (uint32_t p = 0; p < 256; p++) {
|
|
generate_packet_eiger(data_out,
|
|
d_hbm_p0,
|
|
d_hbm_p1,
|
|
hbm_size_bytes,
|
|
f, frame_cell * config.modules + m,
|
|
m, p,
|
|
src_mac_addr,
|
|
config.dest_mac_addr,
|
|
src_ipv4_addr,
|
|
config.dest_ipv4_addr,
|
|
config.exptime,
|
|
config.exptime * f,
|
|
config.debug, 0);
|
|
}
|
|
}
|
|
}
|
|
pulse_id_conv.d += 1.0;
|
|
|
|
if (frame_cell == config.images_in_memory)
|
|
frame_cell = 0;
|
|
else
|
|
frame_cell++;
|
|
}
|
|
return 0;
|
|
}
|