184 lines
6.5 KiB
C++
184 lines
6.5 KiB
C++
// Copyright (2019-2023) Paul Scherrer Institute
|
|
|
|
|
|
#include "hls_jfjoch.h"
|
|
|
|
#ifndef __SYNTHESIS__
|
|
#include <thread>
|
|
#endif
|
|
|
|
inline void write_completion(hls::stream<ap_uint<32> > &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<ap_uint<32> > &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<ap_uint<192>> &integration_in,
|
|
hls::stream<ap_uint<512>> &spot_finder_in,
|
|
hls::stream<axis_completion > &s_axis_completion,
|
|
hls::stream<ap_axiu<512,1,1,1> > &host_memory_out,
|
|
hls::stream<axis_datamover_ctrl> &datamover_out_cmd,
|
|
hls::stream<ap_uint<32> > &s_axis_work_request,
|
|
hls::stream<ap_uint<32> > &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=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 + (FPGA_INTEGRATION_BIN_COUNT)*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); 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; i++) {
|
|
#pragma HLS PIPELINE II=1
|
|
ap_uint<192> tmp;
|
|
integration_in >> tmp;
|
|
packet_out.data = tmp;
|
|
if (i == FPGA_INTEGRATION_BIN_COUNT - 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);
|
|
}
|