// Copyright (2019-2023) Paul Scherrer Institute #include "hls_jfjoch.h" #ifndef __SYNTHESIS__ #include #endif inline void write_completion(hls::stream > &m_axis_completion, const ap_uint<32> &handle, const ap_uint<8> &module_number, const ap_uint<64> &frame_num, const ap_uint<128> &packet_mask, const ap_uint<16> &packet_count, const ap_uint<32> &debug, const ap_uint<64> ×tamp, const ap_uint<64> &bunchid, const ap_uint<32> &exptime, const ap_uint<32> &data_collection_id) { #pragma HLS INLINE ap_uint<1> all_packets_ok = packet_mask.and_reduce(); ap_uint<1> any_packets_received = packet_mask.or_reduce(); ap_uint<8> status = 0; status[0] = all_packets_ok; status[1] = any_packets_received; ap_uint<128> tmp = (handle, packet_count, status, module_number, frame_num); status[7] = tmp.xor_reduce(); // ensure completion has even parity if (handle != HANDLE_SKIP_FRAME) { m_axis_completion << handle; m_axis_completion << (packet_count, status, module_number); m_axis_completion << frame_num(63, 32); m_axis_completion << frame_num(31, 0); m_axis_completion << timestamp(63,32); m_axis_completion << timestamp(31,0); m_axis_completion << bunchid(63,32); m_axis_completion << bunchid(31,0); m_axis_completion << exptime; m_axis_completion << debug; m_axis_completion << 0; m_axis_completion << data_collection_id; m_axis_completion << packet_mask(127,96); m_axis_completion << packet_mask( 95,64); m_axis_completion << packet_mask( 63,32); m_axis_completion << packet_mask( 31, 0); } } inline ap_uint<1> read_request(hls::stream > &s_axis_work_request, ap_uint<32> &handle, ap_uint<64> &address) { #pragma HLS INLINE ap_uint<32> tmp1, tmp2, tmp3, tmp4; s_axis_work_request >> tmp1; s_axis_work_request >> tmp2; s_axis_work_request >> tmp3; s_axis_work_request >> tmp4; handle = tmp1; address = (tmp2, tmp3); ap_uint<128> tmp_all = (tmp1, tmp2, tmp3, tmp4); if (tmp_all.xor_reduce() != 0) return 1; else return 0; } void host_writer(STREAM_512 &data_in, hls::stream> &adu_histo_in, hls::stream> &integration_in, hls::stream> &spot_finder_in, hls::stream &s_axis_completion, hls::stream > &host_memory_out, hls::stream &datamover_out_cmd, hls::stream > &s_axis_work_request, hls::stream > &m_axis_completion, volatile uint64_t &packets_processed, volatile ap_uint<1> &idle, volatile ap_uint<8> &err_reg) { #pragma HLS INTERFACE ap_ctrl_none port=return #pragma HLS INTERFACE register both axis port=data_in #pragma HLS INTERFACE register both axis port=adu_histo_in #pragma HLS INTERFACE register both axis port=integration_in #pragma HLS INTERFACE register both axis port=spot_finder_in #pragma HLS INTERFACE register both axis port=s_axis_completion #pragma HLS INTERFACE register both axis port=host_memory_out #pragma HLS INTERFACE register both axis port=datamover_out_cmd #pragma HLS INTERFACE register both axis port=m_axis_completion #pragma HLS INTERFACE register both axis port=s_axis_work_request #pragma HLS INTERFACE register ap_vld port=packets_processed #pragma HLS INTERFACE register ap_vld port=err_reg #pragma HLS INTERFACE register ap_none port=idle err_reg = 0; idle = 1; ap_uint<32> req_handle; ap_uint<64> req_host_offset; while (data_in.empty()) { #pragma HLS PIPELINE II=4 if (!s_axis_work_request.empty()) read_request(s_axis_work_request, req_handle, req_host_offset); } packet_512_t packet; data_in >> packet; ap_uint<32> data_collection_mode = ACT_REG_MODE(packet.data); ap_uint<32> data_collection_id = data_collection_mode(31, 16); uint64_t internal_packets_processed = 0; packets_processed = internal_packets_processed; write_completion(m_axis_completion, HANDLE_START, 0, 0, 0, 0, 0, 0, 0, 0, data_collection_id); idle = 0; axis_completion cmpl; s_axis_completion >> cmpl; while (!cmpl.last) { read_request(s_axis_work_request, req_handle, req_host_offset); setup_datamover(datamover_out_cmd, req_host_offset, RAW_MODULE_SIZE * sizeof(uint16_t) * (16 + 1) / 16 + 64 + (FPGA_INTEGRATION_BIN_COUNT/4)*64 + ADU_HISTO_BIN_COUNT / 16 * 64); packet_512_t packet_out; packet_out.strb = UINT64_MAX; packet_out.keep = UINT64_MAX; packet_out.dest = 0; packet_out.user = 0; packet_out.id = 0; packet_out.last = 0; for (int i = 0; i < RAW_MODULE_SIZE * sizeof(uint16_t) / 64; i++) { #pragma HLS PIPELINE II=1 data_in >> packet; packet_out.data = packet.data; host_memory_out << packet_out; } for (int i = 0; i < RAW_MODULE_SIZE * sizeof(uint16_t) / (64 * 16) + 1; i++) { #pragma HLS PIPELINE II=1 spot_finder_in >> packet_out.data; host_memory_out << packet_out; } for (int i = 0; i < FPGA_INTEGRATION_BIN_COUNT / 4; i++) { #pragma HLS PIPELINE II=1 integration_in >> packet_out.data; host_memory_out << packet_out; } for (int i = 0; i < ADU_HISTO_BIN_COUNT / 16; i++) { #pragma HLS PIPELINE II=1 ap_uint<512> tmp; adu_histo_in >> packet_out.data; if (i == ADU_HISTO_BIN_COUNT / 16 - 1) packet_out.last = 1; host_memory_out << packet_out; } write_completion(m_axis_completion, req_handle, cmpl.module, cmpl.frame_number, cmpl.packet_mask, cmpl.packet_count, cmpl.debug, cmpl.timestamp, cmpl.bunchid, cmpl.exptime, data_collection_id); internal_packets_processed += cmpl.packet_count; packets_processed = internal_packets_processed; s_axis_completion >> cmpl; } data_in >> packet; write_completion(m_axis_completion, HANDLE_END, 0, 0, 0, 0, 0, 0, 0, 0, data_collection_id); }