// Copyright (2019-2022) Paul Scherrer Institute // SPDX-License-Identifier: CERN-OHL-S-2.0 or GPL-3.0-or-later #include "hls_jfjoch.h" // Loads calibration from host memory based on 64-bit memory addresses loaded in in_mem_location // Expected structure in in_mem_location array: // // * pixel mask for all modules(1 bit/pixel) // * internal packet generator frame // * gain factors for module m at location: 2 + gain level * NMODULES + m // * pedestal factors for module m and storage cell s at location: 2 + 3 * NMODULES + (gain level * 16 + s ) * NMODULES + m void load_data(STREAM_512 &data_out, hls::stream &datamover_in_cmd, hls::stream > &host_memory_in, uint64_t memory_addr, uint64_t size_in_512bit_packets) { setup_datamover(datamover_in_cmd, memory_addr, size_in_512bit_packets * 64); read_internal_pkt_gen_content: for (int j = 0; j < size_in_512bit_packets; j++) { #pragma HLS PIPELINE II=1 ap_axiu<512,1,1,1> data_packet; host_memory_in >> data_packet; packet_512_t packet_out; packet_out.last = 0; packet_out.user = 0; packet_out.id = 0; packet_out.data = data_packet.data; data_out << packet_out; } } void load_calibration(STREAM_512 &data_in, STREAM_512 &data_out, hls::stream &datamover_in_cmd, hls::stream > &host_memory_in, uint64_t in_mem_location[LOAD_CALIBRATION_BRAM_SIZE]) { #pragma HLS INTERFACE ap_ctrl_none port=return #pragma HLS INTERFACE register both axis port=datamover_in_cmd #pragma HLS INTERFACE register both axis port=host_memory_in #pragma HLS INTERFACE register both axis port=data_in #pragma HLS INTERFACE register both axis port=data_out #pragma HLS INTERFACE bram port=in_mem_location storage_type=rom_1p packet_512_t packet_in; data_in >> packet_in; ap_uint<5> modules = ACT_REG_NMODULES(packet_in.data); ap_uint<5> storage_cells = ACT_REG_NSTORAGE_CELLS(packet_in.data); ap_uint<1> conversion = (ACT_REG_MODE(packet_in.data) & MODE_CONV) ? 1 : 0; data_out << packet_in; load_data(data_out, datamover_in_cmd, host_memory_in, in_mem_location[0], RAW_MODULE_SIZE * sizeof(int16_t) / 64); if (conversion) { read_gain: for (int c = 0; c < 3; c++) { // 3 gain levels for (int m = 0; m < modules; m++) { load_data(data_out, datamover_in_cmd, host_memory_in, in_mem_location[m + c * modules + 1], RAW_MODULE_SIZE * sizeof(int16_t) / 64); } } read_pedestal: for (int c = 0; c < 3; c++) { ap_uint<16> offset = (c * 16 + 3) * modules + 1; for (int s = 0; s < storage_cells; s++) { for (int m = 0; m < modules; m++) { load_data(data_out, datamover_in_cmd, host_memory_in, in_mem_location[offset + s * modules + m], RAW_MODULE_SIZE * sizeof(int16_t) / 64); } } } } data_in >> packet_in; while (!packet_in.user) { #pragma HLS PIPELINE II=1 data_out << packet_in; data_in >> packet_in; } data_out << packet_in; }