Compare commits

...

8 Commits

Author SHA1 Message Date
e1045ee3b6 Merge branch '2407-minor-fix' into 'main'
1.0.0-rc.12 Minor fixes

See merge request jungfraujoch/nextgendcu!76
2024-07-08 19:58:27 +02:00
3e5ed2e9f9 1.0.0-rc.12 Minor fixes 2024-07-08 19:58:27 +02:00
3a08733872 Merge branch '2407-versioning' into 'main'
1.0.0-rc.12: Fixes to versioning

See merge request jungfraujoch/nextgendcu!75
2024-07-06 10:56:55 +02:00
00be0bb224 1.0.0-rc.12: Fixes to versioning 2024-07-06 10:56:54 +02:00
c4fc178f7a Merge branch '2406-sqroot' into 'main'
Version 1.0.0-rc.12

See merge request jungfraujoch/nextgendcu!74
2024-07-06 09:34:44 +02:00
6b5fddf2b7 Version 1.0.0-rc.12 2024-07-06 09:34:44 +02:00
2b9ce9a26e Merge branch '2406-more-minor-stuff' into 'main'
v1.0.0_rc.11

See merge request jungfraujoch/nextgendcu!73
2024-06-30 17:48:35 +02:00
3035d9e144 v1.0.0_rc.11 2024-06-30 17:48:35 +02:00
144 changed files with 5249 additions and 3430 deletions

View File

@@ -104,6 +104,7 @@ build:x86:rpm:
- cd build
- source /opt/rh/gcc-toolset-12/enable
- cmake -DCMAKE_BUILD_TYPE=Release ..
- make update_version
- make frontend
- make -j48 package
- mv *.rpm ..
@@ -251,6 +252,7 @@ synthesis:vivado_pcie_100g:
- fpga/pcie_driver/jfjoch_fpga.h
tags:
- vivado
retry: 1
artifacts:
paths:
- "jfjoch_fpga_pcie_100g.mcs"
@@ -284,6 +286,7 @@ synthesis:vivado_pcie_8x10g:
allow_failure: true
tags:
- vivado
retry: 1
artifacts:
paths:
- "jfjoch_fpga_pcie_8x10g.mcs"
@@ -313,8 +316,9 @@ release:
- build:x86:driver
- build:x86:rpm
script:
- export PACKAGE_VERSION=`head -n1 VERSION`
- export PACKAGE_REGISTRY_URL="${CI_API_V4_URL}/projects/${CI_PROJECT_ID}/packages/generic/jungfraujoch/${PACKAGE_VERSION}"
- export PACKAGE_VERSION_SEM=`head -n1 VERSION`
- export PACKAGE_VERSION=${PACKAGE_VERSION_SEM//-/_}
- export PACKAGE_REGISTRY_URL="${CI_API_V4_URL}/projects/${CI_PROJECT_ID}/packages/generic/jungfraujoch/${PACKAGE_VERSION_SEM}"
- 'curl --header "JOB-TOKEN: $CI_JOB_TOKEN" --upload-file jfjoch-driver-dkms-${PACKAGE_VERSION}-1.el8.noarch.rpm "${PACKAGE_REGISTRY_URL}/jfjoch-driver-dkms-${PACKAGE_VERSION}-1.el8.noarch.rpm"'
- 'curl --header "JOB-TOKEN: $CI_JOB_TOKEN" --upload-file jfjoch-writer-${PACKAGE_VERSION}-1.el8.x86_64.rpm "${PACKAGE_REGISTRY_URL}/jfjoch-writer-${PACKAGE_VERSION}-1.el8.x86_64.rpm"'
- 'curl --header "JOB-TOKEN: $CI_JOB_TOKEN" --upload-file jfjoch-${PACKAGE_VERSION}-1.el8.x86_64.rpm "${PACKAGE_REGISTRY_URL}/jfjoch-${PACKAGE_VERSION}-1.el8.x86_64.rpm"'
@@ -323,7 +327,7 @@ release:
- 'curl --header "JOB-TOKEN: $CI_JOB_TOKEN" --upload-file jfjoch_fpga_pcie_100g.mcs "${PACKAGE_REGISTRY_URL}/jfjoch_fpga_pcie_100g.mcs"'
- 'curl --header "JOB-TOKEN: $CI_JOB_TOKEN" --upload-file jfjoch_fpga_pcie_8x10g.mcs "${PACKAGE_REGISTRY_URL}/jfjoch_fpga_pcie_8x10g.mcs"'
- >
release-cli create --name "Release $PACKAGE_VERSION" --tag-name $PACKAGE_VERSION
release-cli create --name "Release $PACKAGE_VERSION_SEM" --tag-name $PACKAGE_VERSION_SEM
--assets-link "{\"name\":\"jfjoch_driver.tar.gz\",\"url\":\"${PACKAGE_REGISTRY_URL}/jfjoch_driver.tar.gz\"}"
--assets-link "{\"name\":\"jfjoch_frontend.tar.gz\",\"url\":\"${PACKAGE_REGISTRY_URL}/jfjoch_frontend.tar.gz\"}"
--assets-link "{\"name\":\"jfjoch_fpga_pcie_8x10g.mcs\",\"url\":\"${PACKAGE_REGISTRY_URL}/jfjoch_fpga_pcie_8x10g.mcs\"}"

View File

@@ -131,13 +131,17 @@ IF (NOT JFJOCH_WRITER_ONLY)
WORKING_DIRECTORY ${CMAKE_SOURCE_DIR}/frontend_ui)
ADD_CUSTOM_TARGET(frontend DEPENDS frontend_ui/build/index.html)
ADD_CUSTOM_TARGET(update_version
COMMAND bash update_version.sh
WORKING_DIRECTORY ${CMAKE_SOURCE_DIR})
INSTALL(DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/fpga/pcie_driver/
DESTINATION /usr/src/jfjoch-1.0.0
DESTINATION /usr/src/jfjoch-${JFJOCH_VERSION}
COMPONENT driver-dkms
FILES_MATCHING PATTERN "dkms.conf")
INSTALL(DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/fpga/pcie_driver/
DESTINATION /usr/src/jfjoch-1.0.0/src
DESTINATION /usr/src/jfjoch-${JFJOCH_VERSION}/src
COMPONENT driver-dkms
FILES_MATCHING PATTERN "*.c" PATTERN "*.h" PATTERN "Makefile")

View File

@@ -1 +1 @@
1.0.0_rc.10
1.0.0-rc.12

View File

@@ -247,6 +247,11 @@ void FPGAAcquisitionDevice::FillActionRegister(const DiffractionExperiment& x, D
if (x.GetPixelDepth() == 4)
job.mode |= MODE_32BIT;
if (x.GetLossyCompressionPoisson()) {
job.mode |= MODE_SQROOT;
job.sqrtmult = x.GetLossyCompressionPoisson().value();
}
}
void FPGAAcquisitionDevice::Start(const DiffractionExperiment &experiment, uint32_t flag) {

View File

@@ -2,117 +2,29 @@
#include "HLSSimulatedDevice.h"
#include <bitset>
#include <arpa/inet.h>
#include "../fpga/hls/datamover_model.h"
#include "../fpga/hls/hls_jfjoch.h"
uint16_t checksum(const uint16_t *addr, size_t count) {
/* Compute Internet Checksum for "count" bytes
* beginning at location "addr".
*/
long sum = 0;
for (int i = 0; i < count / 2; i++)
sum += addr[i];
/* Add left-over byte, if any */
if (count % 2 == 1)
sum += ((uint8_t *) addr)[count / 2];
/* Fold 32-bit sum to 16 bits */
while (sum>>16)
sum = (sum & 0xffff) + (sum >> 16);
return ~sum;
}
HLSSimulatedDevice::HLSSimulatedDevice(uint16_t data_stream, size_t in_frame_buffer_size_modules, int16_t numa_node)
: FPGAAcquisitionDevice(data_stream),
datamover_in(Direction::Input, nullptr),
datamover_out(Direction::Output, nullptr),
datamover_out_hbm_0(Direction::Output, (char *) hbm.data()),
datamover_out_hbm_1(Direction::Output, (char *) hbm.data()),
datamover_in_hbm_0(Direction::Input, (char *) hbm.data()),
datamover_in_hbm_1(Direction::Input, (char *) hbm.data()),
idle(true), hbm(hbm_if_size / 32 * hbm_if_count),
dma_address_table(65536) {
: FPGAAcquisitionDevice(data_stream) {
mac_addr = 0xCCAA11223344;
ipv4_addr = 0x0132010A;
max_modules = MAX_MODULES_FPGA;
if (data_stream != 0)
throw JFJochException(JFJochExceptionCategory::InputParameterInvalid,
"HLS simulation can only work with 1 data_stream, due to use of static variables");
MapBuffersStandard(in_frame_buffer_size_modules, numa_node);
auto in_mem_location32 = (uint32_t *) dma_address_table.data();
for (int i = 0; i < buffer_device.size(); i++) {
in_mem_location32[2 * i ] = ((uint64_t) buffer_device[i]) & UINT32_MAX;
in_mem_location32[2 * i + 1] = ((uint64_t) buffer_device[i]) >> 32;
}
device = std::make_unique<HLSDevice>(buffer_device);
}
void HLSSimulatedDevice::CreateFinalPacket(const DiffractionExperiment& experiment) {
CreateJFPacket(experiment, UINT64_MAX, 0, 0, nullptr, false);
}
void HLSSimulatedDevice::SendPacket(char *buffer, int len, uint8_t user) {
auto obuff = (ap_uint<512> *)buffer;
for (int i = 0; i < (len + 63) / 64; i++) {
packet_512_t packet_in;
if (i == (len + 63) / 64 - 1) packet_in.last = 1;
else packet_in.last = 0;
packet_in.keep = 0xFFFFFFFFFFFFFFFF;
packet_in.user = user;
packet_in.data = obuff[i];
din_eth.write(packet_in);
}
device->CreateFinalPacket(experiment);
}
void HLSSimulatedDevice::CreateJFPacket(const DiffractionExperiment& experiment, uint64_t frame_number, uint32_t eth_packet,
uint32_t module_number, const uint16_t *data, int8_t adjust_axis, uint8_t user) {
char buff[256*64];
memset(buff, 0, 256*64);
auto packet = (jf_raw_packet *)buff;
packet->ether_type = htons(0x0800);
packet->sour_mac[0] = 0x00; // module 0
uint64_t tmp_mac = mac_addr;
for (int i = 0; i < 6; i++)
packet->dest_mac[i] = (tmp_mac >> (8*i)) % 256;
uint32_t half_module = 2 * module_number | ((eth_packet >= 64) ? 1 : 0);
packet->ipv4_header_h = htons(0x4500); // Big endian in IP header!
packet->ipv4_header_total_length = htons(8268); // Big endian in IP header!
packet->ipv4_header_dest_ip = ipv4_addr;
packet->ipv4_header_sour_ip = experiment.GetSrcIPv4Address(data_stream, half_module);
packet->ipv4_header_ttl_protocol = htons(0x0011);
packet->ipv4_header_checksum = checksum( (uint16_t *) &packet->ipv4_header_h, 20); // checksum is already in network order
packet->udp_dest_port = htons(GetUDPPort()); // module number
packet->udp_sour_port = htons(0xDFAC);
packet->udp_length = htons(8248);
// JF headers are little endian
packet->jf.detectortype = SLS_DETECTOR_TYPE_JUNGFRAU;
packet->jf.timestamp = 0xABCDEF0000FEDCBAL;
packet->jf.bunchid = 0x1234567898765431L;
packet->jf.row = half_module;
packet->jf.column = 0;
packet->jf.framenum = frame_number;
packet->jf.packetnum = eth_packet % 64;
if (data != nullptr) {
for (int i = 0; i < 4096; i++)
packet->jf.data[i] = data[i];
}
packet->udp_checksum = htons(checksum( (uint16_t *) (buff+42), 8192+48));
SendPacket(buff, (130+adjust_axis)*64, user);
device->CreateJFPacket(experiment, frame_number, eth_packet, module_number, data, adjust_axis, user);
}
void HLSSimulatedDevice::CreateJFPackets(const DiffractionExperiment& experiment, uint64_t frame_number_0, uint64_t frames,
@@ -126,635 +38,67 @@ void HLSSimulatedDevice::CreateJFPackets(const DiffractionExperiment& experiment
void HLSSimulatedDevice::CreateEIGERPacket(const DiffractionExperiment &experiment, uint64_t frame_number,
uint32_t eth_packet, uint32_t module_number, uint32_t col, uint32_t row,
const uint16_t *data) {
char buff[256*64];
memset(buff, 0, 256*64);
auto packet = (eiger_raw_packet *)buff;
packet->ether_type = htons(0x0800);
packet->sour_mac[0] = 0x00; // module 0
uint64_t tmp_mac = mac_addr;
for (int i = 0; i < 6; i++)
packet->dest_mac[i] = (tmp_mac >> (8*i)) % 256;
packet->ipv4_header_h = htons(0x4500); // Big endian in IP header!
packet->ipv4_header_total_length = htons(4172); // Big endian in IP header!
packet->ipv4_header_dest_ip = ipv4_addr;
packet->ipv4_header_sour_ip = experiment.GetSrcIPv4Address(data_stream, 0);
packet->ipv4_header_ttl_protocol = htons(0x0011);
packet->ipv4_header_checksum = checksum( (uint16_t *) &packet->ipv4_header_h, 20); // checksum is already in network order
packet->udp_dest_port = htons(GetUDPPort()); // module number
packet->udp_sour_port = htons(0xDFAC);
packet->udp_length = htons(4152);
// JF headers are little endian
packet->eiger.detectortype = SLS_DETECTOR_TYPE_EIGER;
packet->eiger.timestamp = 0xABCDEF0000FEDCBAL;
packet->eiger.bunchid = 0x1234567898765431L;
packet->eiger.row = (2 * module_number) | (row % 2);
packet->eiger.column = col % 2;
packet->eiger.framenum = frame_number;
packet->eiger.packetnum = eth_packet % 64;
if (data != nullptr) {
for (int i = 0; i < 2048; i++)
packet->eiger.data[i] = data[i];
}
packet->udp_checksum = htons(checksum( (uint16_t *) (buff+42), 4096+48));
SendPacket(buff, 66*64, 0);
}
AXI_STREAM & HLSSimulatedDevice::OutputStream() {
return dout_eth;
device->CreateEIGERPacket(experiment, frame_number, eth_packet, module_number, col, row, data);
}
void HLSSimulatedDevice::HW_ReadActionRegister(DataCollectionConfig *job) {
memcpy(job, &cfg, sizeof(DataCollectionConfig));
device->HW_ReadActionRegister(job);
}
void HLSSimulatedDevice::HW_WriteActionRegister(const DataCollectionConfig *job) {
memcpy(&cfg, job, sizeof(DataCollectionConfig));
device->HW_WriteActionRegister(job);
}
void HLSSimulatedDevice::FPGA_StartAction(const DiffractionExperiment &experiment) {
if (action_thread.joinable())
action_thread.join();
run_counter += 1;
run_data_collection = 1;
cancel_data_collection = 0;
idle = false;
while (!din_frame_generator.empty())
din_frame_generator.read();
datamover_out.ClearCompletedDescriptors();
action_thread = std::thread(&HLSSimulatedDevice::HLSMainThread, this );
}
void HLSSimulatedDevice::FrameGeneratorFuture(FrameGeneratorConfig config) {
frame_generator(din_frame_generator,
hbm.data(),
hbm.data(),
hbm_if_size,
mac_addr,
ipv4_addr,
cancel_data_collection,
config);
device->FPGA_StartAction(experiment);
}
void HLSSimulatedDevice::HW_RunInternalGenerator(const FrameGeneratorConfig &config) {
frame_generator_future = std::async(std::launch::async, &HLSSimulatedDevice::FrameGeneratorFuture, this, config);
device->HW_RunInternalGenerator(config);
}
void HLSSimulatedDevice::FPGA_EndAction() {
if (action_thread.joinable())
action_thread.join();
device->FPGA_EndAction();
}
HLSSimulatedDevice::~HLSSimulatedDevice() {
if (action_thread.joinable())
action_thread.join();
}
bool HLSSimulatedDevice::HW_ReadMailbox(uint32_t *values) {
std::unique_lock<std::mutex> ul(completion_mutex);
ap_uint<32> tmp;
bool ret = completion_stream.read_nb(tmp);
values[0] = tmp;
// equivalent to driver functionality
if (ret) {
uint32_t data_collection_id = (values[0] >> 16) & 0xFFFF;
uint32_t handle = values[0] & 0xFFFF;
if (handle == HANDLE_START)
completion_count = 0;
else if ((handle != HANDLE_END) && (data_collection_id != DATA_COLLECTION_ID_PURGE)) {
completion_count++;
while (completion_count * DMA_DESCRIPTORS_PER_MODULE > datamover_out.GetCompletedDescriptors())
std::this_thread::sleep_for(std::chrono::milliseconds(1));
}
}
return ret;
return device->HW_ReadMailbox(values);
}
void HLSSimulatedDevice::Cancel() {
cancel_data_collection = 1;
device->Cancel();
}
bool HLSSimulatedDevice::HW_IsIdle() const {
return idle && datamover_out.IsIdle();
return device->HW_IsIdle();
}
bool HLSSimulatedDevice::HW_SendWorkRequest(uint32_t handle) {
work_request_stream.write(handle);
return true;
}
inline uint32_t float2uint(float f) {
float_uint32 fu;
fu.f = f;
return fu.u;
}
void HLSSimulatedDevice::HLSMainThread() {
ap_uint<1> clear_counters = 0;
uint64_t packets_processed;
std::vector<std::thread> hls_cores;
STREAM_512 ip1, udp1, udp2, icmp1, arp1;
STREAM_512 network0;
STREAM_768 stream_768_0;
STREAM_768 stream_768_1;
STREAM_768 stream_768_2;
STREAM_768 stream_768_3;
STREAM_768 stream_768_4;
STREAM_768 stream_768_5;
STREAM_512 data_0;
hls::stream<ap_axiu<512, 1, 1, 1>, 2> data_1;
hls::stream<ap_axiu<512, 1, 1, 1>, 2> data_2;
STREAM_512 data_3;
STREAM_512 data_4;
STREAM_512 data_5;
STREAM_512 data_6;
STREAM_512 data_7;
STREAM_512 data_8;
STREAM_512 data_9;
STREAM_512 data_10;
STREAM_512 data_12;
STREAM_512 data_13;
hls::stream<axis_addr> addr0;
hls::stream<axis_addr> addr1;
hls::stream<axis_addr> addr2;
hls::stream<axis_addr> addr3;
hls::stream<axis_completion> axi_compl[12];
hls::stream<ap_uint<16>> hbm_handles;
hls::stream<ap_uint<512>> adu_histo_result;
hls::stream<ap_axiu<64,1,1,1>> integration_result_0;
hls::stream<ap_uint<512>> integration_result_1;
hls::stream<ap_axiu<32,1,1,1>> spot_finder_result_0;
hls::stream<ap_axiu<32,1,1,1>> spot_finder_result_1;
hls::stream<ap_uint<32>> spot_finder_conn_0;
hls::stream<ap_axiu<32,1,1,1>> spot_finder_result_2;
hls::stream<ap_uint<512>> spot_finder_result_3;
hls::stream<ap_uint<32>> spot_finder_mask_0;
hls::stream<ap_uint<256>> roi_calc_result_0;
hls::stream<ap_uint<UDP_METADATA_STREAM_WIDTH> > udp_metadata;
volatile ap_uint<1> idle_data_collection = 1;
ap_uint<1> load_to_hbm_idle;
ap_uint<1> save_to_hbm_idle;
ap_uint<1> integration_idle;
ap_uint<1> stream_conv_idle;
ap_uint<1> frame_summation_idle;
volatile bool done = false;
volatile bool udp_done = false; // done AND udp_idle
volatile bool sls_done = false; // done AND sls_idle
// Sent gratuitous ARP message
arp(arp1, dout_eth, mac_addr, ipv4_addr, 1, 1);
Logger logger_hls("HLS");
volatile rcv_state_t state = RCV_INIT;
// Start data collection
data_collection_fsm(data_0, data_1,
addr0, addr1,
run_data_collection,
cancel_data_collection,
idle_data_collection,
cfg.mode,
float2uint(cfg.energy_kev),
cfg.nframes,
cfg.nmodules,
cfg.nstorage_cells,
cfg.nsummation , state);
run_data_collection = 0;
data_collection_fsm(data_0, data_1,
addr0, addr1,
run_data_collection,
cancel_data_collection,
idle_data_collection,
cfg.mode,
float2uint(cfg.energy_kev),
cfg.nframes,
cfg.nmodules,
cfg.nstorage_cells,
cfg.nsummation, state);
hls_cores.emplace_back([&] {
while (!udp_done) {
if (din_eth.empty() && din_frame_generator.empty())
std::this_thread::sleep_for(std::chrono::microseconds(10));
else
stream_merge(din_eth, din_frame_generator, network0, data_source);
}
logger_hls.Info("Stream_merge done");
});
hls_cores.emplace_back([&] {
while (!udp_done) {
if (network0.empty())
std::this_thread::sleep_for(std::chrono::microseconds(10));
else
ethernet(network0, ip1, arp1, mac_addr, eth_packets, clear_counters);
}
logger_hls.Info("ethernet done");
});
hls_cores.emplace_back([&] {
while (!udp_done) {
if (ip1.empty())
std::this_thread::sleep_for(std::chrono::microseconds(10));
else
ipv4(ip1, udp1, icmp1, ipv4_addr);
}
logger_hls.Info("ipv4 done");
});
hls_cores.emplace_back([&] {
ap_uint<1> udp_idle = 1;
while (!done || !udp_idle) {
if (udp1.empty())
std::this_thread::sleep_for(std::chrono::microseconds(10));
else
udp(udp1, udp2, udp_metadata, udp_packets, clear_counters, udp_idle);
}
udp_done = true;
logger_hls.Info("udp done");
});
hls_cores.emplace_back([&] {
ap_uint<1> sls_idle = 1;
while (!done || !sls_idle) {
if (udp2.empty())
std::this_thread::sleep_for(std::chrono::microseconds (10));
else
sls_detector(udp2, udp_metadata, data_0, addr0, sls_packets, udp_eth_err, udp_len_err, current_pulse_id,
clear_counters, sls_idle);
}
sls_done = true;
logger_hls.Info("sls_detector done");
});
// 1. Parse incoming UDP packets
hls_cores.emplace_back([&] {
while ((state != RCV_WAIT_FOR_START) || (idle_data_collection.read() == 0) || (!data_0.empty())) {
data_collection_fsm(data_0, data_1,
addr0, addr1,
run_data_collection,
cancel_data_collection,
idle_data_collection,
cfg.mode,
float2uint(cfg.energy_kev),
cfg.nframes,
cfg.nmodules,
cfg.nstorage_cells,
cfg.nsummation,
state);
}
done = true;
logger_hls.Info("data collection done");
});
// 2. Cache images in HBM
hls_cores.emplace_back([&] { save_to_hbm(addr1, axi_compl[0], hbm_handles,
datamover_out_hbm_0.GetCtrlStream(),
datamover_out_hbm_1.GetCtrlStream(),
save_to_hbm_idle,
hbm_if_size);});
hls_cores.emplace_back([&] { save_to_hbm_data(data_1,
data_3,
datamover_out_hbm_0.GetDataStream(),
datamover_out_hbm_1.GetDataStream());});
hls_cores.emplace_back([&] {frame_summation_reorder_compl(data_3, data_4, axi_compl[0], axi_compl[1]);});
hls_cores.emplace_back([&] { load_from_hbm(data_4, data_5, axi_compl[1], axi_compl[2], hbm_handles,
datamover_in_hbm_0.GetDataStream(), datamover_in_hbm_1.GetDataStream(),
datamover_in_hbm_0.GetCtrlStream(), datamover_in_hbm_1.GetCtrlStream(),
load_to_hbm_idle, hbm_if_size);});
hls_cores.emplace_back([&] { pedestal(data_5, data_6, axi_compl[2], axi_compl[3],
hbm.data(),
hbm.data(),
hbm.data(),
hbm.data(),
hbm.data(),
hbm.data(),
hbm.data(),
hbm.data(),
hbm.data(),
hbm.data(),
hbm.data(),
hbm.data(),
hbm_if_size);});
// 3. Calculate histogram of ADU values
hls_cores.emplace_back([&] { adu_histo(data_6, data_7, adu_histo_result, axi_compl[3], axi_compl[4]);});
// 4. Mask missing pixels
hls_cores.emplace_back([&] { mask_missing(data_7, data_8, axi_compl[4], axi_compl[5]);});
// 5. Handle EIGER packets properly
hls_cores.emplace_back([&] { eiger_reorder(data_8, data_9, axi_compl[5], axi_compl[6]);});
// 6. Apply pedestal & gain corrections
hls_cores.emplace_back([&] { jf_conversion(data_9, stream_768_0,
axi_compl[6], axi_compl[7],
hbm.data(),
hbm.data(),
hbm.data(),
hbm.data(),
hbm.data(),
hbm.data(),
hbm.data(),
hbm.data(),
hbm.data(),
hbm.data(),
hbm.data(),
hbm.data(),
hbm_if_size); });
// 7. Frame summation
hls_cores.emplace_back([&] { frame_summation(stream_768_0, stream_768_1, axi_compl[7], axi_compl[8], frame_summation_idle);});
// 8. Integration of pixels
hls_cores.emplace_back([&] { integration(stream_768_1, stream_768_2, integration_result_0, axi_compl[8], axi_compl[9],
hbm.data(), hbm.data(), hbm.data(), hbm.data(), integration_idle, hbm_if_size);});
hls_cores.emplace_back([&] { axis_64_to_512(integration_result_0, integration_result_1);});
// 9. Spot finding
ap_uint<32> tmp_snr_threshold = float2uint(spot_finder_parameters.snr_threshold);
ap_uint<32> min_d = float2uint(spot_finder_parameters.min_d);
ap_uint<32> max_d = float2uint(spot_finder_parameters.max_d);
ap_int<32> tmp_count_threshold = spot_finder_parameters.count_threshold;
ap_uint<32> min_pix_per_spot = spot_finder_parameters.min_pix_per_spot;
hls_cores.emplace_back([&] {
spot_finder_mask(stream_768_2,
stream_768_3,
spot_finder_mask_0,
axi_compl[9],
axi_compl[10],
hbm.data(),
hbm.data(),
min_d,
max_d,
hbm_if_size);
logger_hls.Info("spot_finder_mask done");
});
hls_cores.emplace_back([&] {
spot_finder(stream_768_3, spot_finder_mask_0, stream_768_4, spot_finder_result_0, tmp_count_threshold, tmp_snr_threshold);
logger_hls.Info("spot_finder done");
});
hls_cores.emplace_back([&] {
spot_finder_connectivity(spot_finder_result_0,
spot_finder_result_1,
spot_finder_conn_0);
logger_hls.Info("spot_finder_connectivity done");
});
hls_cores.emplace_back([&] {
spot_finder_merge(spot_finder_result_1,
spot_finder_conn_0,
spot_finder_result_2,
min_pix_per_spot);
logger_hls.Info("spot_finder_merge done");
});
hls_cores.emplace_back([&] {
axis_32_to_512(spot_finder_result_2, spot_finder_result_3);
logger_hls.Info("axis_32_to_512 done");
});
hls_cores.emplace_back([&] {
roi_calc(stream_768_4,
stream_768_5,
roi_calc_result_0,
axi_compl[10],
axi_compl[11],
hbm.data(),
hbm.data(),
hbm_if_size);
logger_hls.Info("roi_calc done");
});
// 10. Reduce/extend 24-bit stream
hls_cores.emplace_back([&] { stream_24bit_conv(stream_768_5, data_12, stream_conv_idle);});
// 11. Prepare data to write to host memory
hls_cores.emplace_back([&] {
ap_uint<3> state;
host_writer(data_12, adu_histo_result, integration_result_1, spot_finder_result_3, roi_calc_result_0,
axi_compl[11], datamover_out.GetDataStream(),
datamover_out.GetCtrlStream(), work_request_stream, completion_stream,
dma_address_table.data(), packets_processed, host_writer_idle, cancel_data_collection, state);
logger_hls.Info("host_writer done");
});
for (auto &i : hls_cores)
i.join();
if (frame_generator_future.valid())
frame_generator_future.get();
// reset static counter
arp(arp1, dout_eth, mac_addr, ipv4_addr, 0, 1);
try {
while (!din_eth.empty())
din_eth.read();
if (!addr1.empty())
throw std::runtime_error("Addr1 queue not empty");
if (!addr2.empty())
throw std::runtime_error("Addr2 queue not empty");
if (!addr3.empty())
throw std::runtime_error("Addr3 queue not empty");
if (!data_1.empty())
throw std::runtime_error("data_1 queue not empty");
if (!data_2.empty())
throw std::runtime_error("data_2 queue not empty");
if (!data_3.empty())
throw std::runtime_error("data_3 queue not empty");
if (!data_4.empty())
throw std::runtime_error("data_4 queue not empty");
if (!data_5.empty())
throw std::runtime_error("data_5 queue not empty");
if (!data_7.empty())
throw std::runtime_error("data_7 queue not empty");
if (!data_8.empty())
throw std::runtime_error("data_8 queue not empty");
if (!data_9.empty())
throw std::runtime_error("data_9 queue not empty");
if (!data_10.empty())
throw std::runtime_error("data_10 queue not empty");
if (!data_12.empty())
throw std::runtime_error("data_12 queue not empty");
if (!data_13.empty())
throw std::runtime_error("data_13 queue not empty");
for (auto &c: axi_compl) {
if (!c.empty())
throw std::runtime_error("Compl queue not empty");
}
if (!stream_768_0.empty())
throw std::runtime_error("stream_768_0 queue not empty");
if (!stream_768_1.empty())
throw std::runtime_error("stream_768_1 queue not empty");
if (!stream_768_2.empty())
throw std::runtime_error("stream_768_2 queue not empty");
if (!stream_768_3.empty())
throw std::runtime_error("stream_768_3 queue not empty");
if (!stream_768_4.empty())
throw std::runtime_error("stream_768_4 queue not empty");
if (!hbm_handles.empty())
throw std::runtime_error("Handles queue not empty");
if (!integration_result_0.empty())
throw std::runtime_error("Integration result queue not empty");
if (!integration_result_1.empty())
throw std::runtime_error("Integration result queue not empty");
if (!datamover_in.GetDataStream().empty())
throw std::runtime_error("Datamover queue is not empty");
while (!datamover_out.IsIdle())
std::this_thread::sleep_for(std::chrono::milliseconds(100));
} catch (const std::runtime_error &e) {
if (logger)
logger->ErrorException(e);
throw e;
}
if (logger)
logger->Info("Packets Eth {} UDP {} SLS {} Proc {}", eth_packets, udp_packets, sls_packets, packets_processed);
idle = true;
return device->HW_SendWorkRequest(handle);
}
DataCollectionStatus HLSSimulatedDevice::GetDataCollectionStatus() const {
DataCollectionStatus status{};
union {
uint64_t u64;
double d;
} pulse_id_conv;
pulse_id_conv.u64 = current_pulse_id;
status.ctrl_reg = ap_uint<1>(host_writer_idle) ? (1 << 4) : 0;
status.max_modules = max_modules;
status.hbm_size_bytes = hbm_if_size;
status.run_counter = run_counter;
status.current_pulseid = pulse_id_conv.d;
status.packets_udp = udp_packets;
status.packets_eth = eth_packets;
status.packets_sls = sls_packets;
return status;
return device->GetDataCollectionStatus();
}
void HLSSimulatedDevice::HW_LoadCalibration(const LoadCalibrationConfig &config) {
int ret = load_calibration(hbm.data(), hbm.data(),
config,
hbm_if_size,
datamover_in.GetCtrlStream(),
datamover_in.GetDataStream(),
dma_address_table.data());
if (ret)
throw JFJochException(JFJochExceptionCategory::AcquisitionDeviceError,
"Error in loading calibration " + std::to_string(ret));
if (!datamover_in.GetDataStream().empty())
throw std::runtime_error("Datamover queue is not empty");
device->HW_LoadCalibration(config);
}
void HLSSimulatedDevice::HW_SetSpotFinderParameters(const SpotFinderParameters &params) {
spot_finder_parameters = params;
device->HW_SetSpotFinderParameters(params);
}
void HLSSimulatedDevice::HW_SetDataSource(uint32_t val) {
data_source = val;
device->HW_SetDataSource(val);
}
uint32_t HLSSimulatedDevice::HW_GetDataSource() {
return data_source;
return device->HW_GetDataSource();
}
void HLSSimulatedDevice::CreateXfelBunchIDPacket(double pulse_id, uint32_t event_code) {
union {
uint64_t u64;
double d;
} pulse_id_conv;
pulse_id_conv.d = pulse_id;
bunchid_raw_packet packet{};
packet.ether_type = htons(0x0800);
for (int i = 0; i < 6; i++)
packet.dest_mac[i] = 0xFF;
packet.ipv4_header_h = htons(0x4500); // Big endian in IP header!
packet.ipv4_header_total_length = htons(sizeof(bunchid_payload) + 8 + 20); // Big endian in IP header!
packet.ipv4_header_dest_ip = UINT32_MAX;
packet.ipv4_header_ttl_protocol = htons(0x0011);
packet.ipv4_header_checksum = checksum( (uint16_t *) &packet.ipv4_header_h, 20); // checksum is already in network order
packet.udp_length = htons(sizeof(bunchid_payload) + 8);
packet.payload.magicn[0] = BUNCHID_MAGICN;
packet.payload.magicn[1] = BUNCHID_MAGICN;
packet.payload.magicn[2] = BUNCHID_MAGICN;
packet.payload.bunchid_msb[0] = (pulse_id_conv.u64 >> 32) & UINT32_MAX;
packet.payload.bunchid_msb[1] = (pulse_id_conv.u64 >> 32) & UINT32_MAX;
packet.payload.bunchid_lsb[0] = pulse_id_conv.u64 & UINT32_MAX;
packet.payload.bunchid_lsb[1] = pulse_id_conv.u64 & UINT32_MAX;
packet.payload.montrig = event_code;
SendPacket((char *) &packet, sizeof(bunchid_raw_packet));
device->CreateXfelBunchIDPacket(pulse_id, event_code);
}

View File

@@ -5,61 +5,13 @@
#include <thread>
#include "../fpga/hls/hls_jfjoch.h"
#include "../fpga/hls/datamover_model.h"
#include "../common/DiffractionExperiment.h"
#include "FPGAAcquisitionDevice.h"
#include "../jungfrau/sls_packet.h"
#include "../fpga/hls/HLSDevice.h"
uint16_t checksum(const uint16_t *addr, size_t count);
#include "FPGAAcquisitionDevice.h"
class HLSSimulatedDevice : public FPGAAcquisitionDevice {
AXI_STREAM din_eth;
AXI_STREAM din_frame_generator;
AXI_STREAM dout_eth;
uint32_t run_counter = 0;
ap_uint<2> data_source = STREAM_MERGE_SRC_NETWORK;
SpotFinderParameters spot_finder_parameters;
uint64_t current_pulse_id = 0;
DataCollectionConfig cfg;
volatile bool idle;
constexpr static const size_t hbm_if_count = 32;
constexpr static const size_t hbm_if_size = 32*1024*1024LU;
std::vector<ap_uint<256>> hbm;
hls::stream<ap_uint<32> > work_request_stream;
hls::stream<ap_uint<32> > completion_stream;
std::mutex completion_mutex;
uint32_t completion_count;
std::thread action_thread;
std::future<void> frame_generator_future;
Datamover<512> datamover_in;
Datamover<512> datamover_out;
Datamover<256> datamover_in_hbm_0;
Datamover<256> datamover_in_hbm_1;
Datamover<256, 16> datamover_out_hbm_0;
Datamover<256, 16> datamover_out_hbm_1;
ap_uint<1> run_data_collection;
ap_uint<1> cancel_data_collection;
volatile ap_uint<1> host_writer_idle;
std::vector<uint64_t> dma_address_table;
uint64_t eth_packets = 0;
uint64_t icmp_packets = 0;
uint64_t udp_packets = 0;
uint64_t sls_packets = 0;
uint32_t udp_len_err = 0;
uint32_t udp_eth_err = 0;
std::unique_ptr<HLSDevice> device;
void HW_ReadActionRegister(DataCollectionConfig *job) override;
void HW_WriteActionRegister(const DataCollectionConfig *job) override;
@@ -74,12 +26,9 @@ class HLSSimulatedDevice : public FPGAAcquisitionDevice {
uint32_t HW_GetDataSource() override;
void HW_SetDataSource(uint32_t val) override;
void HW_RunInternalGenerator(const FrameGeneratorConfig &config) override;
void FrameGeneratorFuture(FrameGeneratorConfig config);
void HLSMainThread();
public:
HLSSimulatedDevice(uint16_t data_stream, size_t in_frame_buffer_size_modules, int16_t numa_node = -1);
~HLSSimulatedDevice() override;
void SendPacket(char *buffer, int len, uint8_t user = 0);
~HLSSimulatedDevice() override = default;
void CreateJFPacket(const DiffractionExperiment& experiment, uint64_t frame_number, uint32_t eth_packet,
uint32_t module_number, const uint16_t *data, int8_t adjust_axis = 0, uint8_t user = 0);
void CreateJFPackets(const DiffractionExperiment& experiment, uint64_t frame_number_0, uint64_t frames,
@@ -90,7 +39,6 @@ public:
void CreateXfelBunchIDPacket(double bunchid, uint32_t event_code);
void CreateFinalPacket(const DiffractionExperiment& experiment);
DataCollectionStatus GetDataCollectionStatus() const override;
AXI_STREAM &OutputStream();
void Cancel() override;
};

View File

@@ -388,6 +388,8 @@ inline DatasetSettings Convert(const org::openapitools::server::model::Dataset_s
else
throw JFJochException(JFJochExceptionCategory::InputParameterInvalid, "Unknown compression");
}
if (input.poissonCompressionIsSet())
ret.LossyCompressionPoisson(input.getPoissonCompression());
if (input.unitCellIsSet())
ret.SetUnitCell(UnitCell{
@@ -423,7 +425,7 @@ inline DatasetSettings Convert(const org::openapitools::server::model::Dataset_s
ret.ImagesPerFile(input.getImagesPerFile());
if (input.dataReductionFactorSerialmxIsSet())
ret.DataReductionFactorSerialMX(input.getDataReductionFactorSerialmx());
ret.LossyCompressionSerialMX(input.getDataReductionFactorSerialmx());
return ret;
}
@@ -475,8 +477,21 @@ void JFJochBrokerHttp::status_get(Pistache::Http::ResponseWriter &response) {
ProcessOutput(Convert(state_machine.GetStatus()), response);
}
void JFJochBrokerHttp::wait_till_done_post(Pistache::Http::ResponseWriter &response) {
auto state = state_machine.WaitTillMeasurementDone(std::chrono::seconds(5));
void JFJochBrokerHttp::wait_till_done_post(const std::optional<int32_t> &timeout,
Pistache::Http::ResponseWriter &response) {
JFJochState state;
if (!timeout)
state = state_machine.WaitTillMeasurementDone(std::chrono::minutes(1));
else if ((timeout.value() > 3600) || (timeout.value() < 0)) {
response.send(Pistache::Http::Code::Bad_Request);
return;
} else if (timeout.value() == 0)
state = state_machine.GetState();
else
state = state_machine.WaitTillMeasurementDone(std::chrono::seconds(timeout.value()));
switch (state) {
case JFJochState::Idle:
response.send(Pistache::Http::Code::Ok);

View File

@@ -90,7 +90,7 @@ class JFJochBrokerHttp : public org::openapitools::server::api::DefaultApi {
void status_get(Pistache::Http::ResponseWriter &response) override;
void wait_till_done_post(Pistache::Http::ResponseWriter &response) override;
void wait_till_done_post(const std::optional<int32_t> &timeoutMs, Pistache::Http::ResponseWriter &response) override;
void trigger_post(Pistache::Http::ResponseWriter &response) override;
void pedestal_post(Pistache::Http::ResponseWriter &response) override;

View File

@@ -2,6 +2,8 @@
#include "JFJochBrokerParser.h"
#include "../common/NetworkAddressConvert.h"
#include "../frame_serialize/ZMQStream2Pusher.h"
#include "../frame_serialize/DumpCBORToFilePusher.h"
inline bool CHECK_ARRAY(const nlohmann::json &j, const std::string& tag) {
if (j.contains(tag)) {
@@ -183,6 +185,7 @@ inline int64_t TimeToUs(const std::string &unit) {
inline std::chrono::microseconds GET_TIME(const nlohmann::json &j, const std::string& tag) {
if (j.contains(tag)) {
// If no units provided for time, this is always microsecond
if (j[tag].is_number())
return std::chrono::microseconds (std::lround(j[tag].get<double>() * 1000.0 * 1000.0));
else if (j[tag].is_string()) {
@@ -300,6 +303,35 @@ void ParseDetectorSetup(const nlohmann::json &j, const std::string& tag, JFJochB
throw JFJochException(JFJochExceptionCategory::JSON, "Detector setup not found");
}
void ParseImagePusher(const nlohmann::json &input, std::unique_ptr<ImagePusher> &image_pusher) {
std::string pusher_type = ParseString(input, "stream_type", "zmq");
if (pusher_type == "zmq") {
int32_t zmq_send_watermark = ParseInt32(input, "zmq_send_watermark", 100);
int32_t zmq_send_buffer_size = ParseInt32(input, "zmq_send_buffer_size", -1);
auto tmp = std::make_unique<ZMQStream2Pusher>(ParseStringArray(input, "zmq_image_addr"),
zmq_send_watermark,
zmq_send_buffer_size);
std::string preview_addr = ParseString(input, "zmq_preview_addr", "");
if (!preview_addr.empty())
tmp->PreviewSocket(preview_addr);
if (input.contains("zmq_preview_period"))
tmp->PreviewCounterPeriod(GET_TIME(input, "zmq_preview_period"));
std::string writer_notification_addr = ParseString(input, "zmq_writer_notification_addr", "");
if (!writer_notification_addr.empty())
tmp->WriterNotificationSocket(writer_notification_addr);
image_pusher = std::move(tmp);
} else if (pusher_type == "dump_cbor") {
image_pusher = std::make_unique<DumpCBORToFilePusher>();
} else
throw JFJochException(JFJochExceptionCategory::InputParameterInvalid,
"stream_type allowed: zmq (default), dump_cbor");
}
void ParseFacilityConfiguration(const nlohmann::json &input, const std::string& tag, DiffractionExperiment &experiment) {
if (CHECK_OBJECT(input, tag)) {
auto j = input[tag];
@@ -328,12 +360,11 @@ void ParseFacilityConfiguration(const nlohmann::json &input, const std::string&
experiment.PedestalG1Frames(GET_I64(j, "pedestal_g1_frames"));
if (j.contains("pedestal_g2_frames"))
experiment.PedestalG2Frames(GET_I64(j, "pedestal_g2_frames"));
if (j.contains("detector_trigger_delay_us"))
experiment.DetectorDelay(GET_TIME(j, "detector_trigger_delay_us"));
if (j.contains("detector_trigger_delay"))
experiment.DetectorDelay(GET_TIME(j, "detector_trigger_delay"));
experiment.FrameTime(GET_TIME(j, "frame_time"), GET_TIME(j, "count_time"));
experiment.FrameTime(GET_TIME(j, "frame_time_us"), GET_TIME(j, "count_time_us"));
if (j.contains("preview_period_us"))
experiment.PreviewPeriod(GET_TIME(j, "preview_period_us"));
experiment.UseInternalPacketGenerator(GET_BOOL(j, "internal_frame_generator", false));
if (experiment.IsUsingInternalPacketGen())
experiment.ConversionOnFPGA(false);

View File

@@ -14,6 +14,7 @@ DetectorGeometry ParseDetectorGeometry(const nlohmann::json &j);
DetectorSetup ParseDetectorSetup(const nlohmann::json &j);
void ParseDetectorSetup(const nlohmann::json &j, const std::string& tag, JFJochBrokerHttp& broker);
void ParseFacilityConfiguration(const nlohmann::json &j, const std::string& tag, DiffractionExperiment &experiment);
void ParseImagePusher(const nlohmann::json &j, std::unique_ptr<ImagePusher> &image_pusher);
void ParseAcquisitionDeviceGroup(const nlohmann::json &input, const std::string& tag, AcquisitionDeviceGroup &aq_devices);
std::vector<std::string> ParseStringArray(const nlohmann::json &input, const std::string& tag);

View File

@@ -340,12 +340,6 @@ void JFJochStateMachine::Start(const DatasetSettings& settings) {
}
}
void JFJochStateMachine::WaitTillMeasurementDone() {
std::unique_lock<std::mutex> ul(m);
c.wait(ul, [&] { return !IsRunning(); });
}
void JFJochStateMachine::MeasurementThread() {
try {
auto tmp_output = services.Stop();
@@ -659,6 +653,14 @@ bool JFJochStateMachine::IsRunning() const {
}
}
JFJochState JFJochStateMachine::WaitTillMeasurementDone() {
std::unique_lock<std::mutex> ul(m);
c.wait(ul, [&] { return !IsRunning(); });
return state;
}
JFJochState JFJochStateMachine::WaitTillMeasurementDone(std::chrono::milliseconds timeout) {
std::unique_lock<std::mutex> ul(m);

View File

@@ -141,7 +141,7 @@ public:
void Pedestal();
void Deactivate();
void Start(const DatasetSettings& settings);
void WaitTillMeasurementDone();
JFJochState WaitTillMeasurementDone();
JFJochState WaitTillMeasurementDone(std::chrono::milliseconds timeout);
void Trigger();

39
broker/gen/api/ApiBase.h Normal file
View File

@@ -0,0 +1,39 @@
/**
* Jungfraujoch
* Jungfraujoch Broker Web API
*
* The version of the OpenAPI document: 1.0.0-rc.12
* Contact: filip.leonarski@psi.ch
*
* NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech).
* https://openapi-generator.tech
* Do not edit the class manually.
*/
/*
* ApiBase.h
*
* Generalization of the Api classes
*/
#ifndef ApiBase_H_
#define ApiBase_H_
#include <pistache/router.h>
#include <memory>
namespace org::openapitools::server::api
{
class ApiBase {
public:
explicit ApiBase(const std::shared_ptr<Pistache::Rest::Router>& rtr) : router(rtr) {};
virtual ~ApiBase() = default;
virtual void init() = 0;
protected:
const std::shared_ptr<Pistache::Rest::Router> router;
};
} // namespace org::openapitools::server::api
#endif /* ApiBase_H_ */

View File

@@ -2,7 +2,7 @@
* Jungfraujoch
* Jungfraujoch Broker Web API
*
* The version of the OpenAPI document: 1.0.0_rc.10
* The version of the OpenAPI document: 1.0.0-rc.12
* Contact: filip.leonarski@psi.ch
*
* NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech).
@@ -22,7 +22,7 @@ using namespace org::openapitools::server::model;
const std::string DefaultApi::base = "";
DefaultApi::DefaultApi(const std::shared_ptr<Pistache::Rest::Router>& rtr)
: router(rtr)
: ApiBase(rtr)
{
}
@@ -1275,12 +1275,22 @@ void DefaultApi::version_get_handler(const Pistache::Rest::Request &, Pistache::
}
}
void DefaultApi::wait_till_done_post_handler(const Pistache::Rest::Request &, Pistache::Http::ResponseWriter response) {
void DefaultApi::wait_till_done_post_handler(const Pistache::Rest::Request &request, Pistache::Http::ResponseWriter response) {
try {
// Getting the query params
auto timeoutQuery = request.query().get("timeout");
std::optional<int32_t> timeout;
if(timeoutQuery.has_value()){
int32_t valueQuery_instance;
if(fromStringValue(timeoutQuery.value(), valueQuery_instance)){
timeout = valueQuery_instance;
}
}
try {
this->wait_till_done_post(response);
this->wait_till_done_post(timeout, response);
} catch (Pistache::Http::HttpError &e) {
response.send(static_cast<Pistache::Http::Code>(e.code()), e.what());
return;

View File

@@ -2,7 +2,7 @@
* Jungfraujoch
* Jungfraujoch Broker Web API
*
* The version of the OpenAPI document: 1.0.0_rc.10
* The version of the OpenAPI document: 1.0.0-rc.12
* Contact: filip.leonarski@psi.ch
*
* NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech).
@@ -19,6 +19,8 @@
#define DefaultApi_H_
#include "ApiBase.h"
#include <pistache/http.h>
#include <pistache/router.h>
#include <pistache/http_headers.h>
@@ -42,15 +44,16 @@
#include "Roi_circle_list.h"
#include "Spot_finding_settings.h"
#include <string>
#include <vector>
namespace org::openapitools::server::api
{
class DefaultApi {
class DefaultApi : public ApiBase {
public:
explicit DefaultApi(const std::shared_ptr<Pistache::Rest::Router>& rtr);
virtual ~DefaultApi() = default;
void init();
~DefaultApi() override = default;
void init() override;
static const std::string base;
@@ -109,8 +112,6 @@ private:
void xfel_pulse_id_get_handler(const Pistache::Rest::Request &request, Pistache::Http::ResponseWriter response);
void default_api_default_handler(const Pistache::Rest::Request &request, Pistache::Http::ResponseWriter response);
const std::shared_ptr<Pistache::Rest::Router> router;
/// <summary>
/// Helper function to handle unexpected Exceptions during Parameter parsing and validation.
/// May be overridden to return custom error formats. This is called inside a catch block.
@@ -479,9 +480,10 @@ private:
/// Wait for acquisition done
/// </summary>
/// <remarks>
/// Block execution of external script till initialization, data collection or pedestal is finished. Running this command does not affect (cancel) running data collection, it is only to ensure synchronous execution of other software. To not block web server for a long period of time, the procedure is provided with a timeout of 5 seconds.
/// Block execution of external script till initialization, data collection or pedestal is finished. Running this command does not affect (cancel) running data collection, it is only to ensure synchronous execution of other software. To not block web server for a indefinite period of time, the procedure is provided with a timeout. Extending timeout is possible, but requires to ensure safety that client will not close the connection and retry the connection.
/// </remarks>
virtual void wait_till_done_post(Pistache::Http::ResponseWriter &response) = 0;
/// <param name="timeout">Timeout in seconds (0 &#x3D;&#x3D; immediate response) (optional, default to 60)</param>
virtual void wait_till_done_post(const std::optional<int32_t> &timeout, Pistache::Http::ResponseWriter &response) = 0;
/// <summary>
/// Return XFEL event codes for the current data acquisition
/// </summary>

View File

@@ -2,7 +2,7 @@
* Jungfraujoch
* Jungfraujoch Broker Web API
*
* The version of the OpenAPI document: 1.0.0_rc.10
* The version of the OpenAPI document: 1.0.0-rc.12
* Contact: filip.leonarski@psi.ch
*
* NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech).
@@ -114,7 +114,7 @@ bool Broker_status::operator!=(const Broker_status& rhs) const
void to_json(nlohmann::json& j, const Broker_status& o)
{
j = nlohmann::json();
j = nlohmann::json::object();
j["state"] = o.m_State;
if(o.progressIsSet())
j["progress"] = o.m_Progress;

View File

@@ -2,7 +2,7 @@
* Jungfraujoch
* Jungfraujoch Broker Web API
*
* The version of the OpenAPI document: 1.0.0_rc.10
* The version of the OpenAPI document: 1.0.0-rc.12
* Contact: filip.leonarski@psi.ch
*
* NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech).
@@ -78,8 +78,8 @@ public:
bool indexingRateIsSet() const;
void unsetIndexing_rate();
friend void to_json(nlohmann::json& j, const Broker_status& o);
friend void from_json(const nlohmann::json& j, Broker_status& o);
friend void to_json(nlohmann::json& j, const Broker_status& o);
friend void from_json(const nlohmann::json& j, Broker_status& o);
protected:
std::string m_State;

View File

@@ -2,7 +2,7 @@
* Jungfraujoch
* Jungfraujoch Broker Web API
*
* The version of the OpenAPI document: 1.0.0_rc.10
* The version of the OpenAPI document: 1.0.0-rc.12
* Contact: filip.leonarski@psi.ch
*
* NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech).
@@ -98,7 +98,7 @@ bool Calibration_statistics_inner::operator!=(const Calibration_statistics_inner
void to_json(nlohmann::json& j, const Calibration_statistics_inner& o)
{
j = nlohmann::json();
j = nlohmann::json::object();
j["module_number"] = o.m_Module_number;
j["storage_cell_number"] = o.m_Storage_cell_number;
j["pedestal_g0_mean"] = o.m_Pedestal_g0_mean;

View File

@@ -2,7 +2,7 @@
* Jungfraujoch
* Jungfraujoch Broker Web API
*
* The version of the OpenAPI document: 1.0.0_rc.10
* The version of the OpenAPI document: 1.0.0-rc.12
* Contact: filip.leonarski@psi.ch
*
* NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech).
@@ -103,8 +103,8 @@ public:
int64_t getMaskedPixels() const;
void setMaskedPixels(int64_t const value);
friend void to_json(nlohmann::json& j, const Calibration_statistics_inner& o);
friend void from_json(const nlohmann::json& j, Calibration_statistics_inner& o);
friend void to_json(nlohmann::json& j, const Calibration_statistics_inner& o);
friend void from_json(const nlohmann::json& j, Calibration_statistics_inner& o);
protected:
int64_t m_Module_number;

View File

@@ -2,7 +2,7 @@
* Jungfraujoch
* Jungfraujoch Broker Web API
*
* The version of the OpenAPI document: 1.0.0_rc.10
* The version of the OpenAPI document: 1.0.0-rc.12
* Contact: filip.leonarski@psi.ch
*
* NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech).
@@ -38,6 +38,7 @@ Dataset_settings::Dataset_settings()
m_Space_group_number = 0L;
m_Space_group_numberIsSet = false;
m_Sample_name = "";
m_Sample_nameIsSet = false;
m_Fpga_output = "auto";
m_Fpga_outputIsSet = false;
m_Compression = "bslz4";
@@ -59,6 +60,8 @@ Dataset_settings::Dataset_settings()
m_Run_nameIsSet = false;
m_Experiment_group = "";
m_Experiment_groupIsSet = false;
m_Poisson_compression = 0L;
m_Poisson_compressionIsSet = false;
m_Unit_cellIsSet = false;
}
@@ -256,7 +259,26 @@ bool Dataset_settings::validate(std::stringstream& msg, const std::string& pathP
}
}
if (poissonCompressionIsSet())
{
const int64_t& value = m_Poisson_compression;
const std::string currentValuePath = _pathPrefix + ".poissonCompression";
if (value < 0ll)
{
success = false;
msg << currentValuePath << ": must be greater than or equal to 0;";
}
if (value > 16ll)
{
success = false;
msg << currentValuePath << ": must be less than or equal to 16;";
}
}
return success;
}
@@ -295,8 +317,8 @@ bool Dataset_settings::operator==(const Dataset_settings& rhs) const
((!spaceGroupNumberIsSet() && !rhs.spaceGroupNumberIsSet()) || (spaceGroupNumberIsSet() && rhs.spaceGroupNumberIsSet() && getSpaceGroupNumber() == rhs.getSpaceGroupNumber())) &&
(getSampleName() == rhs.getSampleName())
&&
((!sampleNameIsSet() && !rhs.sampleNameIsSet()) || (sampleNameIsSet() && rhs.sampleNameIsSet() && getSampleName() == rhs.getSampleName())) &&
((!fpgaOutputIsSet() && !rhs.fpgaOutputIsSet()) || (fpgaOutputIsSet() && rhs.fpgaOutputIsSet() && getFpgaOutput() == rhs.getFpgaOutput())) &&
@@ -335,6 +357,9 @@ bool Dataset_settings::operator==(const Dataset_settings& rhs) const
((!experimentGroupIsSet() && !rhs.experimentGroupIsSet()) || (experimentGroupIsSet() && rhs.experimentGroupIsSet() && getExperimentGroup() == rhs.getExperimentGroup())) &&
((!poissonCompressionIsSet() && !rhs.poissonCompressionIsSet()) || (poissonCompressionIsSet() && rhs.poissonCompressionIsSet() && getPoissonCompression() == rhs.getPoissonCompression())) &&
((!unitCellIsSet() && !rhs.unitCellIsSet()) || (unitCellIsSet() && rhs.unitCellIsSet() && getUnitCell() == rhs.getUnitCell()))
;
@@ -347,7 +372,7 @@ bool Dataset_settings::operator!=(const Dataset_settings& rhs) const
void to_json(nlohmann::json& j, const Dataset_settings& o)
{
j = nlohmann::json();
j = nlohmann::json::object();
if(o.imagesPerTriggerIsSet())
j["images_per_trigger"] = o.m_Images_per_trigger;
if(o.ntriggerIsSet())
@@ -364,7 +389,8 @@ void to_json(nlohmann::json& j, const Dataset_settings& o)
j["images_per_file"] = o.m_Images_per_file;
if(o.spaceGroupNumberIsSet())
j["space_group_number"] = o.m_Space_group_number;
j["sample_name"] = o.m_Sample_name;
if(o.sampleNameIsSet())
j["sample_name"] = o.m_Sample_name;
if(o.fpgaOutputIsSet())
j["fpga_output"] = o.m_Fpga_output;
if(o.compressionIsSet())
@@ -389,6 +415,8 @@ void to_json(nlohmann::json& j, const Dataset_settings& o)
j["run_name"] = o.m_Run_name;
if(o.experimentGroupIsSet())
j["experiment_group"] = o.m_Experiment_group;
if(o.poissonCompressionIsSet())
j["poisson_compression"] = o.m_Poisson_compression;
if(o.unitCellIsSet())
j["unit_cell"] = o.m_Unit_cell;
@@ -430,7 +458,11 @@ void from_json(const nlohmann::json& j, Dataset_settings& o)
j.at("space_group_number").get_to(o.m_Space_group_number);
o.m_Space_group_numberIsSet = true;
}
j.at("sample_name").get_to(o.m_Sample_name);
if(j.find("sample_name") != j.end())
{
j.at("sample_name").get_to(o.m_Sample_name);
o.m_Sample_nameIsSet = true;
}
if(j.find("fpga_output") != j.end())
{
j.at("fpga_output").get_to(o.m_Fpga_output);
@@ -491,6 +523,11 @@ void from_json(const nlohmann::json& j, Dataset_settings& o)
j.at("experiment_group").get_to(o.m_Experiment_group);
o.m_Experiment_groupIsSet = true;
}
if(j.find("poisson_compression") != j.end())
{
j.at("poisson_compression").get_to(o.m_Poisson_compression);
o.m_Poisson_compressionIsSet = true;
}
if(j.find("unit_cell") != j.end())
{
j.at("unit_cell").get_to(o.m_Unit_cell);
@@ -640,6 +677,15 @@ std::string Dataset_settings::getSampleName() const
void Dataset_settings::setSampleName(std::string const& value)
{
m_Sample_name = value;
m_Sample_nameIsSet = true;
}
bool Dataset_settings::sampleNameIsSet() const
{
return m_Sample_nameIsSet;
}
void Dataset_settings::unsetSample_name()
{
m_Sample_nameIsSet = false;
}
std::string Dataset_settings::getFpgaOutput() const
{
@@ -845,6 +891,23 @@ void Dataset_settings::unsetExperiment_group()
{
m_Experiment_groupIsSet = false;
}
int64_t Dataset_settings::getPoissonCompression() const
{
return m_Poisson_compression;
}
void Dataset_settings::setPoissonCompression(int64_t const value)
{
m_Poisson_compression = value;
m_Poisson_compressionIsSet = true;
}
bool Dataset_settings::poissonCompressionIsSet() const
{
return m_Poisson_compressionIsSet;
}
void Dataset_settings::unsetPoisson_compression()
{
m_Poisson_compressionIsSet = false;
}
org::openapitools::server::model::Dataset_settings_unit_cell Dataset_settings::getUnitCell() const
{
return m_Unit_cell;

View File

@@ -2,7 +2,7 @@
* Jungfraujoch
* Jungfraujoch Broker Web API
*
* The version of the OpenAPI document: 1.0.0_rc.10
* The version of the OpenAPI document: 1.0.0-rc.12
* Contact: filip.leonarski@psi.ch
*
* NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech).
@@ -76,7 +76,7 @@ public:
bool ntriggerIsSet() const;
void unsetNtrigger();
/// <summary>
/// Image time. If not provided (or zero value) the frame time is assumed as default. For JUNGFRAU, image time must be multiple of frame time, up to 256 * frame_time. In XFEL mode: summation happens for frames collected with multiple triggers. Ignored for storage cells and if raw data are saved.
/// Image time. If not provided (or zero value) the frame time is assumed as default. Image time must be multiple of frame time; max value is 256 * frame_time. In XFEL mode: summation happens for frames collected with multiple triggers. Ignored for storage cells and if raw data are saved.
/// </summary>
int64_t getImageTimeUs() const;
void setImageTimeUs(int64_t const value);
@@ -128,6 +128,8 @@ public:
/// </summary>
std::string getSampleName() const;
void setSampleName(std::string const& value);
bool sampleNameIsSet() const;
void unsetSample_name();
/// <summary>
/// FPGA output data type
/// </summary>
@@ -213,6 +215,13 @@ public:
bool experimentGroupIsSet() const;
void unsetExperiment_group();
/// <summary>
/// Enable lossy compression of pixel values that preserves Poisson statistics. Requires to provide a numerical factor SQ. Pixel value P will be transformed to round(sqrt(P) * SQ), with rounding to the closest integer. Compression is turned off if the value is missing or it is set to zero.
/// </summary>
int64_t getPoissonCompression() const;
void setPoissonCompression(int64_t const value);
bool poissonCompressionIsSet() const;
void unsetPoisson_compression();
/// <summary>
///
/// </summary>
org::openapitools::server::model::Dataset_settings_unit_cell getUnitCell() const;
@@ -220,8 +229,8 @@ public:
bool unitCellIsSet() const;
void unsetUnit_cell();
friend void to_json(nlohmann::json& j, const Dataset_settings& o);
friend void from_json(const nlohmann::json& j, Dataset_settings& o);
friend void to_json(nlohmann::json& j, const Dataset_settings& o);
friend void from_json(const nlohmann::json& j, Dataset_settings& o);
protected:
int64_t m_Images_per_trigger;
bool m_Images_per_triggerIsSet;
@@ -244,7 +253,7 @@ protected:
int64_t m_Space_group_number;
bool m_Space_group_numberIsSet;
std::string m_Sample_name;
bool m_Sample_nameIsSet;
std::string m_Fpga_output;
bool m_Fpga_outputIsSet;
std::string m_Compression;
@@ -269,6 +278,8 @@ protected:
bool m_Run_nameIsSet;
std::string m_Experiment_group;
bool m_Experiment_groupIsSet;
int64_t m_Poisson_compression;
bool m_Poisson_compressionIsSet;
org::openapitools::server::model::Dataset_settings_unit_cell m_Unit_cell;
bool m_Unit_cellIsSet;

View File

@@ -2,7 +2,7 @@
* Jungfraujoch
* Jungfraujoch Broker Web API
*
* The version of the OpenAPI document: 1.0.0_rc.10
* The version of the OpenAPI document: 1.0.0-rc.12
* Contact: filip.leonarski@psi.ch
*
* NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech).
@@ -185,7 +185,7 @@ bool Dataset_settings_unit_cell::operator!=(const Dataset_settings_unit_cell& rh
void to_json(nlohmann::json& j, const Dataset_settings_unit_cell& o)
{
j = nlohmann::json();
j = nlohmann::json::object();
j["a"] = o.m_a;
j["b"] = o.m_b;
j["c"] = o.m_c;

View File

@@ -2,7 +2,7 @@
* Jungfraujoch
* Jungfraujoch Broker Web API
*
* The version of the OpenAPI document: 1.0.0_rc.10
* The version of the OpenAPI document: 1.0.0-rc.12
* Contact: filip.leonarski@psi.ch
*
* NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech).
@@ -88,8 +88,8 @@ public:
float getGamma() const;
void setGamma(float const value);
friend void to_json(nlohmann::json& j, const Dataset_settings_unit_cell& o);
friend void from_json(const nlohmann::json& j, Dataset_settings_unit_cell& o);
friend void to_json(nlohmann::json& j, const Dataset_settings_unit_cell& o);
friend void from_json(const nlohmann::json& j, Dataset_settings_unit_cell& o);
protected:
float m_a;

View File

@@ -2,7 +2,7 @@
* Jungfraujoch
* Jungfraujoch Broker Web API
*
* The version of the OpenAPI document: 1.0.0_rc.10
* The version of the OpenAPI document: 1.0.0-rc.12
* Contact: filip.leonarski@psi.ch
*
* NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech).
@@ -90,7 +90,7 @@ bool Detector_list::operator!=(const Detector_list& rhs) const
void to_json(nlohmann::json& j, const Detector_list& o)
{
j = nlohmann::json();
j = nlohmann::json::object();
j["detectors"] = o.m_Detectors;
j["current_id"] = o.m_Current_id;

View File

@@ -2,7 +2,7 @@
* Jungfraujoch
* Jungfraujoch Broker Web API
*
* The version of the OpenAPI document: 1.0.0_rc.10
* The version of the OpenAPI document: 1.0.0-rc.12
* Contact: filip.leonarski@psi.ch
*
* NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech).
@@ -70,8 +70,8 @@ public:
int64_t getCurrentId() const;
void setCurrentId(int64_t const value);
friend void to_json(nlohmann::json& j, const Detector_list& o);
friend void from_json(const nlohmann::json& j, Detector_list& o);
friend void to_json(nlohmann::json& j, const Detector_list& o);
friend void from_json(const nlohmann::json& j, Detector_list& o);
protected:
std::vector<org::openapitools::server::model::Detector_list_detectors_inner> m_Detectors;

View File

@@ -2,7 +2,7 @@
* Jungfraujoch
* Jungfraujoch Broker Web API
*
* The version of the OpenAPI document: 1.0.0_rc.10
* The version of the OpenAPI document: 1.0.0-rc.12
* Contact: filip.leonarski@psi.ch
*
* NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech).
@@ -96,7 +96,7 @@ bool Detector_list_detectors_inner::operator!=(const Detector_list_detectors_inn
void to_json(nlohmann::json& j, const Detector_list_detectors_inner& o)
{
j = nlohmann::json();
j = nlohmann::json::object();
j["id"] = o.m_Id;
j["description"] = o.m_Description;
j["nmodules"] = o.m_Nmodules;

View File

@@ -2,7 +2,7 @@
* Jungfraujoch
* Jungfraujoch Broker Web API
*
* The version of the OpenAPI document: 1.0.0_rc.10
* The version of the OpenAPI document: 1.0.0-rc.12
* Contact: filip.leonarski@psi.ch
*
* NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech).
@@ -84,8 +84,8 @@ public:
int64_t getHeight() const;
void setHeight(int64_t const value);
friend void to_json(nlohmann::json& j, const Detector_list_detectors_inner& o);
friend void from_json(const nlohmann::json& j, Detector_list_detectors_inner& o);
friend void to_json(nlohmann::json& j, const Detector_list_detectors_inner& o);
friend void from_json(const nlohmann::json& j, Detector_list_detectors_inner& o);
protected:
int64_t m_Id;

View File

@@ -2,7 +2,7 @@
* Jungfraujoch
* Jungfraujoch Broker Web API
*
* The version of the OpenAPI document: 1.0.0_rc.10
* The version of the OpenAPI document: 1.0.0-rc.12
* Contact: filip.leonarski@psi.ch
*
* NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech).
@@ -66,7 +66,7 @@ bool Detector_selection::operator!=(const Detector_selection& rhs) const
void to_json(nlohmann::json& j, const Detector_selection& o)
{
j = nlohmann::json();
j = nlohmann::json::object();
j["id"] = o.m_Id;
}

View File

@@ -2,7 +2,7 @@
* Jungfraujoch
* Jungfraujoch Broker Web API
*
* The version of the OpenAPI document: 1.0.0_rc.10
* The version of the OpenAPI document: 1.0.0-rc.12
* Contact: filip.leonarski@psi.ch
*
* NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech).
@@ -63,8 +63,8 @@ public:
int64_t getId() const;
void setId(int64_t const value);
friend void to_json(nlohmann::json& j, const Detector_selection& o);
friend void from_json(const nlohmann::json& j, Detector_selection& o);
friend void to_json(nlohmann::json& j, const Detector_selection& o);
friend void from_json(const nlohmann::json& j, Detector_selection& o);
protected:
int64_t m_Id;

View File

@@ -2,7 +2,7 @@
* Jungfraujoch
* Jungfraujoch Broker Web API
*
* The version of the OpenAPI document: 1.0.0_rc.10
* The version of the OpenAPI document: 1.0.0-rc.12
* Contact: filip.leonarski@psi.ch
*
* NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech).
@@ -220,7 +220,7 @@ bool Detector_settings::operator!=(const Detector_settings& rhs) const
void to_json(nlohmann::json& j, const Detector_settings& o)
{
j = nlohmann::json();
j = nlohmann::json::object();
j["frame_time_us"] = o.m_Frame_time_us;
if(o.countTimeUsIsSet())
j["count_time_us"] = o.m_Count_time_us;

View File

@@ -2,7 +2,7 @@
* Jungfraujoch
* Jungfraujoch Broker Web API
*
* The version of the OpenAPI document: 1.0.0_rc.10
* The version of the OpenAPI document: 1.0.0-rc.12
* Contact: filip.leonarski@psi.ch
*
* NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech).
@@ -147,8 +147,8 @@ public:
bool useGainHg0IsSet() const;
void unsetUse_gain_hg0();
friend void to_json(nlohmann::json& j, const Detector_settings& o);
friend void from_json(const nlohmann::json& j, Detector_settings& o);
friend void to_json(nlohmann::json& j, const Detector_settings& o);
friend void from_json(const nlohmann::json& j, Detector_settings& o);
protected:
int64_t m_Frame_time_us;

View File

@@ -2,7 +2,7 @@
* Jungfraujoch
* Jungfraujoch Broker Web API
*
* The version of the OpenAPI document: 1.0.0_rc.10
* The version of the OpenAPI document: 1.0.0-rc.12
* Contact: filip.leonarski@psi.ch
*
* NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech).
@@ -126,7 +126,7 @@ bool Detector_status::operator!=(const Detector_status& rhs) const
void to_json(nlohmann::json& j, const Detector_status& o)
{
j = nlohmann::json();
j = nlohmann::json::object();
j["state"] = o.m_State;
j["powerchip"] = o.m_Powerchip;
j["server_version"] = o.m_Server_version;

View File

@@ -2,7 +2,7 @@
* Jungfraujoch
* Jungfraujoch Broker Web API
*
* The version of the OpenAPI document: 1.0.0_rc.10
* The version of the OpenAPI document: 1.0.0-rc.12
* Contact: filip.leonarski@psi.ch
*
* NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech).
@@ -90,8 +90,8 @@ public:
std::vector<int64_t> getHighVoltageV() const;
void setHighVoltageV(std::vector<int64_t> const value);
friend void to_json(nlohmann::json& j, const Detector_status& o);
friend void from_json(const nlohmann::json& j, Detector_status& o);
friend void to_json(nlohmann::json& j, const Detector_status& o);
friend void from_json(const nlohmann::json& j, Detector_status& o);
protected:
std::string m_State;

View File

@@ -2,7 +2,7 @@
* Jungfraujoch
* Jungfraujoch Broker Web API
*
* The version of the OpenAPI document: 1.0.0_rc.10
* The version of the OpenAPI document: 1.0.0-rc.12
* Contact: filip.leonarski@psi.ch
*
* NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech).
@@ -70,7 +70,7 @@ bool Error_message::operator!=(const Error_message& rhs) const
void to_json(nlohmann::json& j, const Error_message& o)
{
j = nlohmann::json();
j = nlohmann::json::object();
j["msg"] = o.m_Msg;
j["reason"] = o.m_Reason;

View File

@@ -2,7 +2,7 @@
* Jungfraujoch
* Jungfraujoch Broker Web API
*
* The version of the OpenAPI document: 1.0.0_rc.10
* The version of the OpenAPI document: 1.0.0-rc.12
* Contact: filip.leonarski@psi.ch
*
* NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech).
@@ -69,8 +69,8 @@ public:
std::string getReason() const;
void setReason(std::string const& value);
friend void to_json(nlohmann::json& j, const Error_message& o);
friend void from_json(const nlohmann::json& j, Error_message& o);
friend void to_json(nlohmann::json& j, const Error_message& o);
friend void from_json(const nlohmann::json& j, Error_message& o);
protected:
std::string m_Msg;

View File

@@ -2,7 +2,7 @@
* Jungfraujoch
* Jungfraujoch Broker Web API
*
* The version of the OpenAPI document: 1.0.0_rc.10
* The version of the OpenAPI document: 1.0.0-rc.12
* Contact: filip.leonarski@psi.ch
*
* NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech).

View File

@@ -2,7 +2,7 @@
* Jungfraujoch
* Jungfraujoch Broker Web API
*
* The version of the OpenAPI document: 1.0.0_rc.10
* The version of the OpenAPI document: 1.0.0-rc.12
* Contact: filip.leonarski@psi.ch
*
* NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech).

View File

@@ -2,7 +2,7 @@
* Jungfraujoch
* Jungfraujoch Broker Web API
*
* The version of the OpenAPI document: 1.0.0_rc.10
* The version of the OpenAPI document: 1.0.0-rc.12
* Contact: filip.leonarski@psi.ch
*
* NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech).
@@ -185,7 +185,7 @@ bool Measurement_statistics::operator!=(const Measurement_statistics& rhs) const
void to_json(nlohmann::json& j, const Measurement_statistics& o)
{
j = nlohmann::json();
j = nlohmann::json::object();
if(o.filePrefixIsSet())
j["file_prefix"] = o.m_File_prefix;
if(o.runNumberIsSet())

View File

@@ -2,7 +2,7 @@
* Jungfraujoch
* Jungfraujoch Broker Web API
*
* The version of the OpenAPI document: 1.0.0_rc.10
* The version of the OpenAPI document: 1.0.0-rc.12
* Contact: filip.leonarski@psi.ch
*
* NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech).
@@ -185,8 +185,8 @@ public:
bool unitCellIsSet() const;
void unsetUnit_cell();
friend void to_json(nlohmann::json& j, const Measurement_statistics& o);
friend void from_json(const nlohmann::json& j, Measurement_statistics& o);
friend void to_json(nlohmann::json& j, const Measurement_statistics& o);
friend void from_json(const nlohmann::json& j, Measurement_statistics& o);
protected:
std::string m_File_prefix;
bool m_File_prefixIsSet;

View File

@@ -2,7 +2,7 @@
* Jungfraujoch
* Jungfraujoch Broker Web API
*
* The version of the OpenAPI document: 1.0.0_rc.10
* The version of the OpenAPI document: 1.0.0-rc.12
* Contact: filip.leonarski@psi.ch
*
* NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech).
@@ -114,7 +114,7 @@ bool Plot::operator!=(const Plot& rhs) const
void to_json(nlohmann::json& j, const Plot& o)
{
j = nlohmann::json();
j = nlohmann::json::object();
j["title"] = o.m_Title;
j["x"] = o.m_x;
j["y"] = o.m_y;

View File

@@ -2,7 +2,7 @@
* Jungfraujoch
* Jungfraujoch Broker Web API
*
* The version of the OpenAPI document: 1.0.0_rc.10
* The version of the OpenAPI document: 1.0.0-rc.12
* Contact: filip.leonarski@psi.ch
*
* NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech).
@@ -75,8 +75,8 @@ public:
std::vector<float> getY() const;
void setY(std::vector<float> const value);
friend void to_json(nlohmann::json& j, const Plot& o);
friend void from_json(const nlohmann::json& j, Plot& o);
friend void to_json(nlohmann::json& j, const Plot& o);
friend void from_json(const nlohmann::json& j, Plot& o);
protected:
std::string m_Title;

View File

@@ -2,7 +2,7 @@
* Jungfraujoch
* Jungfraujoch Broker Web API
*
* The version of the OpenAPI document: 1.0.0_rc.10
* The version of the OpenAPI document: 1.0.0-rc.12
* Contact: filip.leonarski@psi.ch
*
* NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech).
@@ -91,7 +91,7 @@ bool Plots::operator!=(const Plots& rhs) const
void to_json(nlohmann::json& j, const Plots& o)
{
j = nlohmann::json();
j = nlohmann::json::object();
if(o.titleIsSet())
j["title"] = o.m_Title;
j["plot"] = o.m_Plot;

View File

@@ -2,7 +2,7 @@
* Jungfraujoch
* Jungfraujoch Broker Web API
*
* The version of the OpenAPI document: 1.0.0_rc.10
* The version of the OpenAPI document: 1.0.0-rc.12
* Contact: filip.leonarski@psi.ch
*
* NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech).
@@ -73,8 +73,8 @@ public:
std::vector<org::openapitools::server::model::Plot> getPlot() const;
void setPlot(std::vector<org::openapitools::server::model::Plot> const& value);
friend void to_json(nlohmann::json& j, const Plots& o);
friend void from_json(const nlohmann::json& j, Plots& o);
friend void to_json(nlohmann::json& j, const Plots& o);
friend void from_json(const nlohmann::json& j, Plots& o);
protected:
std::string m_Title;
bool m_TitleIsSet;

View File

@@ -2,7 +2,7 @@
* Jungfraujoch
* Jungfraujoch Broker Web API
*
* The version of the OpenAPI document: 1.0.0_rc.10
* The version of the OpenAPI document: 1.0.0-rc.12
* Contact: filip.leonarski@psi.ch
*
* NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech).
@@ -153,7 +153,7 @@ bool Preview_settings::operator!=(const Preview_settings& rhs) const
void to_json(nlohmann::json& j, const Preview_settings& o)
{
j = nlohmann::json();
j = nlohmann::json::object();
j["saturation"] = o.m_Saturation;
if(o.showSpotsIsSet())
j["show_spots"] = o.m_Show_spots;

View File

@@ -2,7 +2,7 @@
* Jungfraujoch
* Jungfraujoch Broker Web API
*
* The version of the OpenAPI document: 1.0.0_rc.10
* The version of the OpenAPI document: 1.0.0-rc.12
* Contact: filip.leonarski@psi.ch
*
* NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech).
@@ -105,8 +105,8 @@ public:
bool resolutionRingIsSet() const;
void unsetResolution_ring();
friend void to_json(nlohmann::json& j, const Preview_settings& o);
friend void from_json(const nlohmann::json& j, Preview_settings& o);
friend void to_json(nlohmann::json& j, const Preview_settings& o);
friend void from_json(const nlohmann::json& j, Preview_settings& o);
protected:
int64_t m_Saturation;

View File

@@ -2,7 +2,7 @@
* Jungfraujoch
* Jungfraujoch Broker Web API
*
* The version of the OpenAPI document: 1.0.0_rc.10
* The version of the OpenAPI document: 1.0.0-rc.12
* Contact: filip.leonarski@psi.ch
*
* NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech).
@@ -102,7 +102,7 @@ bool Rad_int_settings::operator!=(const Rad_int_settings& rhs) const
void to_json(nlohmann::json& j, const Rad_int_settings& o)
{
j = nlohmann::json();
j = nlohmann::json::object();
if(o.polarizationFactorIsSet())
j["polarization_factor"] = o.m_Polarization_factor;
j["solid_angle_corr"] = o.m_Solid_angle_corr;

View File

@@ -2,7 +2,7 @@
* Jungfraujoch
* Jungfraujoch Broker Web API
*
* The version of the OpenAPI document: 1.0.0_rc.10
* The version of the OpenAPI document: 1.0.0-rc.12
* Contact: filip.leonarski@psi.ch
*
* NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech).
@@ -85,8 +85,8 @@ public:
float getQSpacing() const;
void setQSpacing(float const value);
friend void to_json(nlohmann::json& j, const Rad_int_settings& o);
friend void from_json(const nlohmann::json& j, Rad_int_settings& o);
friend void to_json(nlohmann::json& j, const Rad_int_settings& o);
friend void from_json(const nlohmann::json& j, Rad_int_settings& o);
protected:
float m_Polarization_factor;
bool m_Polarization_factorIsSet;

View File

@@ -2,7 +2,7 @@
* Jungfraujoch
* Jungfraujoch Broker Web API
*
* The version of the OpenAPI document: 1.0.0_rc.10
* The version of the OpenAPI document: 1.0.0-rc.12
* Contact: filip.leonarski@psi.ch
*
* NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech).
@@ -152,7 +152,7 @@ bool Roi_box::operator!=(const Roi_box& rhs) const
void to_json(nlohmann::json& j, const Roi_box& o)
{
j = nlohmann::json();
j = nlohmann::json::object();
j["name"] = o.m_Name;
j["min_x_pxl"] = o.m_Min_x_pxl;
j["max_x_pxl"] = o.m_Max_x_pxl;

View File

@@ -2,7 +2,7 @@
* Jungfraujoch
* Jungfraujoch Broker Web API
*
* The version of the OpenAPI document: 1.0.0_rc.10
* The version of the OpenAPI document: 1.0.0-rc.12
* Contact: filip.leonarski@psi.ch
*
* NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech).
@@ -84,8 +84,8 @@ public:
int64_t getMaxYPxl() const;
void setMaxYPxl(int64_t const value);
friend void to_json(nlohmann::json& j, const Roi_box& o);
friend void from_json(const nlohmann::json& j, Roi_box& o);
friend void to_json(nlohmann::json& j, const Roi_box& o);
friend void from_json(const nlohmann::json& j, Roi_box& o);
protected:
std::string m_Name;

View File

@@ -2,7 +2,7 @@
* Jungfraujoch
* Jungfraujoch Broker Web API
*
* The version of the OpenAPI document: 1.0.0_rc.10
* The version of the OpenAPI document: 1.0.0-rc.12
* Contact: filip.leonarski@psi.ch
*
* NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech).
@@ -92,7 +92,7 @@ bool Roi_box_list::operator!=(const Roi_box_list& rhs) const
void to_json(nlohmann::json& j, const Roi_box_list& o)
{
j = nlohmann::json();
j = nlohmann::json::object();
if(o.roisIsSet() || !o.m_Rois.empty())
j["rois"] = o.m_Rois;

View File

@@ -2,7 +2,7 @@
* Jungfraujoch
* Jungfraujoch Broker Web API
*
* The version of the OpenAPI document: 1.0.0_rc.10
* The version of the OpenAPI document: 1.0.0-rc.12
* Contact: filip.leonarski@psi.ch
*
* NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech).
@@ -67,8 +67,8 @@ public:
bool roisIsSet() const;
void unsetRois();
friend void to_json(nlohmann::json& j, const Roi_box_list& o);
friend void from_json(const nlohmann::json& j, Roi_box_list& o);
friend void to_json(nlohmann::json& j, const Roi_box_list& o);
friend void from_json(const nlohmann::json& j, Roi_box_list& o);
protected:
std::vector<org::openapitools::server::model::Roi_box> m_Rois;
bool m_RoisIsSet;

View File

@@ -2,7 +2,7 @@
* Jungfraujoch
* Jungfraujoch Broker Web API
*
* The version of the OpenAPI document: 1.0.0_rc.10
* The version of the OpenAPI document: 1.0.0-rc.12
* Contact: filip.leonarski@psi.ch
*
* NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech).
@@ -106,7 +106,7 @@ bool Roi_circle::operator!=(const Roi_circle& rhs) const
void to_json(nlohmann::json& j, const Roi_circle& o)
{
j = nlohmann::json();
j = nlohmann::json::object();
j["name"] = o.m_Name;
j["center_x_pxl"] = o.m_Center_x_pxl;
j["center_y_pxl"] = o.m_Center_y_pxl;

View File

@@ -2,7 +2,7 @@
* Jungfraujoch
* Jungfraujoch Broker Web API
*
* The version of the OpenAPI document: 1.0.0_rc.10
* The version of the OpenAPI document: 1.0.0-rc.12
* Contact: filip.leonarski@psi.ch
*
* NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech).
@@ -79,8 +79,8 @@ public:
float getRadiusPxl() const;
void setRadiusPxl(float const value);
friend void to_json(nlohmann::json& j, const Roi_circle& o);
friend void from_json(const nlohmann::json& j, Roi_circle& o);
friend void to_json(nlohmann::json& j, const Roi_circle& o);
friend void from_json(const nlohmann::json& j, Roi_circle& o);
protected:
std::string m_Name;

View File

@@ -2,7 +2,7 @@
* Jungfraujoch
* Jungfraujoch Broker Web API
*
* The version of the OpenAPI document: 1.0.0_rc.10
* The version of the OpenAPI document: 1.0.0-rc.12
* Contact: filip.leonarski@psi.ch
*
* NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech).
@@ -91,7 +91,7 @@ bool Roi_circle_list::operator!=(const Roi_circle_list& rhs) const
void to_json(nlohmann::json& j, const Roi_circle_list& o)
{
j = nlohmann::json();
j = nlohmann::json::object();
j["rois"] = o.m_Rois;
}

View File

@@ -2,7 +2,7 @@
* Jungfraujoch
* Jungfraujoch Broker Web API
*
* The version of the OpenAPI document: 1.0.0_rc.10
* The version of the OpenAPI document: 1.0.0-rc.12
* Contact: filip.leonarski@psi.ch
*
* NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech).
@@ -65,8 +65,8 @@ public:
std::vector<org::openapitools::server::model::Roi_circle> getRois() const;
void setRois(std::vector<org::openapitools::server::model::Roi_circle> const& value);
friend void to_json(nlohmann::json& j, const Roi_circle_list& o);
friend void from_json(const nlohmann::json& j, Roi_circle_list& o);
friend void to_json(nlohmann::json& j, const Roi_circle_list& o);
friend void from_json(const nlohmann::json& j, Roi_circle_list& o);
protected:
std::vector<org::openapitools::server::model::Roi_circle> m_Rois;

View File

@@ -2,7 +2,7 @@
* Jungfraujoch
* Jungfraujoch Broker Web API
*
* The version of the OpenAPI document: 1.0.0_rc.10
* The version of the OpenAPI document: 1.0.0-rc.12
* Contact: filip.leonarski@psi.ch
*
* NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech).
@@ -125,7 +125,7 @@ bool Rotation_axis::operator!=(const Rotation_axis& rhs) const
void to_json(nlohmann::json& j, const Rotation_axis& o)
{
j = nlohmann::json();
j = nlohmann::json::object();
if(o.nameIsSet())
j["name"] = o.m_Name;
j["step"] = o.m_Step;

View File

@@ -2,7 +2,7 @@
* Jungfraujoch
* Jungfraujoch Broker Web API
*
* The version of the OpenAPI document: 1.0.0_rc.10
* The version of the OpenAPI document: 1.0.0-rc.12
* Contact: filip.leonarski@psi.ch
*
* NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech).
@@ -86,8 +86,8 @@ public:
bool vectorIsSet() const;
void unsetVector();
friend void to_json(nlohmann::json& j, const Rotation_axis& o);
friend void from_json(const nlohmann::json& j, Rotation_axis& o);
friend void to_json(nlohmann::json& j, const Rotation_axis& o);
friend void from_json(const nlohmann::json& j, Rotation_axis& o);
protected:
std::string m_Name;
bool m_NameIsSet;

View File

@@ -2,7 +2,7 @@
* Jungfraujoch
* Jungfraujoch Broker Web API
*
* The version of the OpenAPI document: 1.0.0_rc.10
* The version of the OpenAPI document: 1.0.0-rc.12
* Contact: filip.leonarski@psi.ch
*
* NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech).
@@ -197,7 +197,7 @@ bool Spot_finding_settings::operator!=(const Spot_finding_settings& rhs) const
void to_json(nlohmann::json& j, const Spot_finding_settings& o)
{
j = nlohmann::json();
j = nlohmann::json::object();
j["enable"] = o.m_Enable;
j["indexing"] = o.m_Indexing;
if(o.filterPowderRingsIsSet())

View File

@@ -2,7 +2,7 @@
* Jungfraujoch
* Jungfraujoch Broker Web API
*
* The version of the OpenAPI document: 1.0.0_rc.10
* The version of the OpenAPI document: 1.0.0-rc.12
* Contact: filip.leonarski@psi.ch
*
* NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech).
@@ -117,8 +117,8 @@ public:
float getIndexingTolerance() const;
void setIndexingTolerance(float const value);
friend void to_json(nlohmann::json& j, const Spot_finding_settings& o);
friend void from_json(const nlohmann::json& j, Spot_finding_settings& o);
friend void to_json(nlohmann::json& j, const Spot_finding_settings& o);
friend void from_json(const nlohmann::json& j, Spot_finding_settings& o);
protected:
bool m_Enable;

View File

@@ -2,7 +2,7 @@ openapi: 3.0.3
info:
title: Jungfraujoch
description: Jungfraujoch Broker Web API
version: 1.0.0_rc.10
version: 1.0.0-rc.12
contact:
email: filip.leonarski@psi.ch
components:
@@ -45,7 +45,6 @@ components:
- beam_y_pxl
- detector_distance_mm
- incident_energy_keV
- sample_name
properties:
images_per_trigger:
type: integer
@@ -117,6 +116,7 @@ components:
maximum: 194
sample_name:
type: string
default: ""
description: |
/entry/sample/name in NXmx
Sample name
@@ -198,6 +198,16 @@ components:
description: |
Name of group owning the data (e.g. p-group or proposal number).
Transferred over CBOR stream, though not saved in HDF5 file.
poisson_compression:
type: integer
format: int64
minimum: 0
maximum: 16
description: |
Enable lossy compression of pixel values that preserves Poisson statistics.
Requires to provide a numerical factor SQ.
Pixel value P will be transformed to round(sqrt(P) * SQ), with rounding to the closest integer.
Compression is turned off if the value is missing or it is set to zero.
unit_cell:
type: object
description: Units of angstrom and degree
@@ -853,22 +863,37 @@ paths:
/wait_till_done:
post:
summary: Wait for acquisition done
parameters:
- in: query
name: timeout
required: false
schema:
type: integer
default: 60
minimum: 0
maximum: 3600
description: Timeout in seconds (0 == immediate response)
description: |
Block execution of external script till initialization, data collection or pedestal is finished.
Running this command does not affect (cancel) running data collection, it is only to ensure synchronous execution of other software.
To not block web server for a long period of time, the procedure is provided with a timeout of 5 seconds.
To not block web server for a indefinite period of time, the procedure is provided with a timeout.
Extending timeout is possible, but requires to ensure safety that client will not close the connection and retry the connection.
responses:
"200":
description: Detector in `Idle` state, another data collection can start immediately
"400":
description: Timeout parameter out of bounds
"500":
description: Error within Jungfraujoch code - see output message.
content:
application/json:
schema:
$ref: '#/components/schemas/error_message'
"502":
description: Detector is inactive mode
"504":
description: 5 second timeout reached, need to restart operation
description: Timeout reached, need to restart operation
/trigger:
post:

View File

@@ -12,8 +12,6 @@
#include "JFJochBrokerHttp.h"
#include "JFJochBrokerParser.h"
#include "../frame_serialize/ZMQStream2Pusher.h"
#include "../frame_serialize/DumpCBORToFilePusher.h"
static Pistache::Http::Endpoint *httpEndpoint;
@@ -81,25 +79,7 @@ int main (int argc, char **argv) {
if (aq_devices.size() > 0) {
experiment.DataStreams(aq_devices.size());
std::string pusher_type = ParseString(input, "stream_type", "zmq");
if (pusher_type == "zmq") {
int32_t zmq_send_watermark = ParseInt32(input, "zmq_send_watermark", 100);
int32_t zmq_send_buffer_size = ParseInt32(input, "zmq_send_buffer_size", -1);
auto tmp = std::make_unique<ZMQStream2Pusher>(ParseStringArray(input, "zmq_image_addr"),
zmq_send_watermark,
zmq_send_buffer_size);
std::string preview_addr = ParseString(input, "zmq_preview_addr", "");
if (!preview_addr.empty())
tmp->PreviewSocket(preview_addr);
image_pusher = std::move(tmp);
} else if (pusher_type == "dump_cbor") {
image_pusher = std::make_unique<DumpCBORToFilePusher>();
} else
throw JFJochException(JFJochExceptionCategory::InputParameterInvalid,
"stream_type allowed: zmq (default), dump_cbor");
ParseImagePusher(input, image_pusher);
int32_t send_buffer_size_MiB = ParseInt32(input, "send_buffer_size_MiB", 2048);
receiver = std::make_unique<JFJochReceiverService>(aq_devices, logger, *image_pusher, send_buffer_size_MiB);

File diff suppressed because one or more lines are too long

View File

@@ -299,14 +299,14 @@ int64_t DatasetSettings::GetImagesPerFile() const {
return images_per_file;
}
DatasetSettings &DatasetSettings::DataReductionFactorSerialMX(float input) {
DatasetSettings &DatasetSettings::LossyCompressionSerialMX(float input) {
check_min("Data reduction factor for serial MX", input, 0.0);
check_max("Data reduction factor for serial MX", input, 1.0);
data_reduction_factor_serialmx = input;
return *this;
}
float DatasetSettings::GetDataReductionFactorSerialMX() const {
float DatasetSettings::GetLossyCompressionSerialMX() const {
return data_reduction_factor_serialmx;
}
@@ -355,3 +355,18 @@ DatasetSettings &DatasetSettings::ImageTime(const std::optional<std::chrono::mic
image_time = input;
return *this;
}
DatasetSettings &DatasetSettings::LossyCompressionPoisson(std::optional<int64_t> input) {
if (!input || (input == 0))
compression_poisson_factor = {};
else {
check_min("Poisson compression factor", input.value(), 1);
check_max("Poisson compression factor", input.value(), 16);
compression_poisson_factor = input;
}
return *this;
}
std::optional<int64_t> DatasetSettings::GetLossyCompressionPoisson() const {
return compression_poisson_factor;
}

View File

@@ -51,6 +51,7 @@ class DatasetSettings {
std::optional<uint64_t> run_number;
std::optional<std::string> run_name;
std::string group;
std::optional<int64_t> compression_poisson_factor;
public:
DatasetSettings();
@@ -75,12 +76,14 @@ public:
DatasetSettings& PhotonEnergyMultiplayer(float input);
DatasetSettings& FPGAOutputMode(FPGAPixelOutput input);
DatasetSettings& ImagesPerFile(int64_t input);
DatasetSettings& DataReductionFactorSerialMX(float input);
DatasetSettings& RunNumber(const std::optional<uint64_t> &run_number);
DatasetSettings& RunName(const std::optional<std::string> &input);
DatasetSettings& ExperimentGroup(const std::string &group);
DatasetSettings& ImageTime(const std::optional<std::chrono::microseconds> input);
DatasetSettings& LossyCompressionSerialMX(float input);
DatasetSettings& LossyCompressionPoisson(std::optional<int64_t> input);
std::optional<float> GetAttenuatorTransmission() const;
std::optional<float> GetTotalFlux() const;
std::optional<GoniometerAxis> GetGoniometer() const;
@@ -106,12 +109,14 @@ public:
int64_t GetNumTriggers() const;
int64_t GetImageNumPerTrigger() const;
int64_t GetImagesPerFile() const;
float GetDataReductionFactorSerialMX() const;
std::optional<uint64_t> GetRunNumber() const;
std::optional<std::string> GetRunName() const;
std::string GetExperimentGroup() const;
std::optional<std::chrono::microseconds> GetImageTime() const;
float GetLossyCompressionSerialMX() const;
std::optional<int64_t> GetLossyCompressionPoisson() const;
};
#endif //JUNGFRAUJOCH_DATASETSETTINGS_H

View File

@@ -761,7 +761,7 @@ void DiffractionExperiment::FillMessage(StartMessage &message) const {
for (const auto &[x, y]: roi_mask.GetROINameMap())
message.roi_names.emplace_back(x);
message.data_reduction_factor_serialmx = GetDataReductionFactorSerialMX();
message.data_reduction_factor_serialmx = GetLossyCompressionSerialMX();
message.experiment_group = dataset.GetExperimentGroup();
message.jfjoch_release = jfjoch_version();
message.detector_serial_number = detector.GetSerialNumber();
@@ -1205,12 +1205,21 @@ int64_t DiffractionExperiment::GetSendBufferLocationSize() const {
return GetMaxCompressedSize() + 1024 * 1024;
}
float DiffractionExperiment::GetDataReductionFactorSerialMX() const {
return dataset.GetDataReductionFactorSerialMX();
float DiffractionExperiment::GetLossyCompressionSerialMX() const {
return dataset.GetLossyCompressionSerialMX();
}
DiffractionExperiment &DiffractionExperiment::DataReductionFactorSerialMX(float input) {
dataset.DataReductionFactorSerialMX(input);
DiffractionExperiment &DiffractionExperiment::LossyCompressionSerialMX(float input) {
dataset.LossyCompressionSerialMX(input);
return *this;
}
std::optional<int64_t> DiffractionExperiment::GetLossyCompressionPoisson() const {
return dataset.GetLossyCompressionPoisson();
}
DiffractionExperiment &DiffractionExperiment::LossyCompressionPoisson(std::optional<int64_t> input) {
dataset.LossyCompressionPoisson(input);
return *this;
}

View File

@@ -100,6 +100,8 @@ class DiffractionExperiment {
int64_t max_spot_count;
int64_t summation;
std::string detector_update_zmq_addr;
public:
// Public methods are atomic
DiffractionExperiment();
@@ -169,7 +171,8 @@ public:
DiffractionExperiment& FPGAOutputMode(FPGAPixelOutput input);
DiffractionExperiment& MaxSpotCount(int64_t input);
DiffractionExperiment& ImagesPerFile(int64_t input);
DiffractionExperiment& DataReductionFactorSerialMX(float input);
DiffractionExperiment& LossyCompressionSerialMX(float input);
DiffractionExperiment& LossyCompressionPoisson(std::optional<int64_t> input);
DiffractionExperiment& ImportDatasetSettings(const DatasetSettings& input);
DatasetSettings GetDatasetSettings() const;
@@ -322,7 +325,8 @@ public:
void ExportROIMap(uint16_t *v, size_t module_number) const;
int64_t GetImagesPerFile() const;
float GetDataReductionFactorSerialMX() const;
float GetLossyCompressionSerialMX() const;
std::optional<int64_t> GetLossyCompressionPoisson() const;
std::string GetExperimentGroup() const;
};

View File

@@ -65,14 +65,14 @@ void DetectorWrapper::Initialize(const DiffractionExperiment& experiment,
det.setSourceUDPIP(sls::IpAddr(cfg.ipv4_src_addr_1), {i});
det.setSourceUDPMAC(sls::MacAddr(BASE_DETECTOR_MAC + i * 2), {i});
det.setDestinationUDPPort(cfg.udp_dest_port_1, i);
det.setDestinationUDPPort(cfg.udp_dest_port_1 + 2 * i, i);
det.setDestinationUDPIP(sls::IpAddr(cfg.ipv4_dest_addr_1), {i});
det.setDestinationUDPMAC(sls::MacAddr(cfg.mac_addr_dest_1), {i});
if (experiment.GetUDPInterfaceCount() == 2) {
det.setSourceUDPIP2(sls::IpAddr(cfg.ipv4_src_addr_2), {i});
det.setSourceUDPMAC2(sls::MacAddr(BASE_DETECTOR_MAC + i * 2 + 1), {i});
det.setDestinationUDPPort2(cfg.udp_dest_port_2, i);
det.setDestinationUDPPort2(cfg.udp_dest_port_2 + 2 * i + 1, i);
det.setDestinationUDPIP2(sls::IpAddr(cfg.ipv4_dest_addr_2), {i});
det.setDestinationUDPMAC2(sls::MacAddr(cfg.mac_addr_dest_2), {i});
}
@@ -100,8 +100,8 @@ void DetectorWrapper::Initialize(const DiffractionExperiment& experiment,
auto &cfg = mod_cfg[i];
det.setDestinationUDPPort(cfg.udp_dest_port_1, 2 * i);
det.setDestinationUDPPort2(cfg.udp_dest_port_1, 2 * i + 1);
det.setDestinationUDPPort(cfg.udp_dest_port_1 + 2 * i, 2 * i);
det.setDestinationUDPPort2(cfg.udp_dest_port_1 + 2 * i + 1, 2 * i + 1);
det.setSourceUDPIP(sls::IpAddr(cfg.ipv4_src_addr_1), {2 * i, 2 * i + 1});
det.setDestinationUDPIP(sls::IpAddr(cfg.ipv4_dest_addr_1), {2 * i, 2 * i + 1});
det.setDestinationUDPMAC(sls::MacAddr(cfg.mac_addr_dest_1), {2 * i, 2 * i + 1});

View File

@@ -8,13 +8,13 @@
"pedestal_g0_frames": 2000,
"pedestal_g1_frames": 300,
"pedestal_g2_frames": 300,
"frame_time_us": "500 us",
"count_time_us": "480 us",
"preview_period_us": "1 s",
"frame_time": "500 us",
"count_time": "480 us",
"detector_ipv4": "10.10.85.0"
},
"frontend_directory":"/home/jungfrau/nextgendcu/frontend/build",
"numa_policy": "n2g2",
"zmq_preview_period": "1 s",
"zmq_image_addr": ["tcp://0.0.0.0:5500", "tcp://0.0.0.0:5501", "tcp://0.0.0.0:5502", "tcp://0.0.0.0:5503"],
"receiver_threads": 64,
"receiver": {

View File

@@ -8,15 +8,16 @@
"pedestal_g0_frames": 2000,
"pedestal_g1_frames": 300,
"pedestal_g2_frames": 300,
"frame_time_us": "10 ms",
"count_time_us": "10 us",
"preview_period_us": "1 s",
"frame_time": "10 ms",
"count_time": "10 us",
"detector_ipv4": "10.3.30.155",
"pulsed_source": true
},
"frontend_directory":"/home/jungfrau/nextgendcu/frontend/build",
"numa_policy": "n2g4",
"zmq_image_addr": ["tcp://0.0.0.0:5500"],
"zmq_preview_period": "1 s",
"receiver_threads": 64,
"receiver": {
"type": "pcie",

View File

@@ -8,9 +8,8 @@
"pedestal_g0_frames": 0,
"pedestal_g1_frames": 0,
"pedestal_g2_frames": 0,
"frame_time_us": "1000 us",
"count_time_us": "980 us",
"preview_period_us": "1 s",
"frame_time": "1000 us",
"count_time": "980 us",
"detector_ipv4": "10.10.85.20",
"internal_frame_generator": true
},
@@ -20,6 +19,9 @@
},
"frontend_directory": "../../frontend_ui/build/",
"zmq_image_addr": ["tcp://0.0.0.0:5500"],
"zmq_preview_addr": "tcp://0.0.0.0:5501",
"zmq_preview_period": "1 s",
"zmq_writer_notification_addr": "ipc://*",
"detectors": [
{
"standard_geometry": {

View File

@@ -12,8 +12,6 @@ ELSE()
MESSAGE(STATUS "Xilinx HLS compiler not found")
ENDIF()
INCLUDE_DIRECTORIES(include)
ADD_SUBDIRECTORY(hls)
ADD_SUBDIRECTORY(pcie_driver)
ADD_SUBDIRECTORY(host_library)

View File

@@ -75,7 +75,9 @@
`define ADDR_NSTORAGE_CELLS 16'h021C
`define ADDR_NSUMMATION 16'h0220
`define ADDR_DATA_SOURCE 16'h0224
`define ADDR_SQRTMULT 16'h0224
`define ADDR_DATA_SOURCE 16'h0300
module action_config
#(parameter C_S_AXI_ADDR_WIDTH = 16,
@@ -114,6 +116,7 @@ module action_config
output reg [4:0] nmodules ,
output reg [3:0] nstorage_cells ,
output reg [7:0] nsummation ,
output reg [7:0] sqrtmult ,
output reg [1:0] data_source ,
output wire [31:0] hbm_size_bytes ,
@@ -366,6 +369,9 @@ always @(posedge clk) begin
`ADDR_NSUMMATION: begin
rdata <= nsummation;
end
`ADDR_SQRTMULT: begin
rdata <= sqrtmult;
end
`ADDR_DATA_SOURCE: begin
rdata <= data_source;
end
@@ -639,6 +645,15 @@ always @(posedge clk) begin
end
end
always @(posedge clk) begin
if (!resetn)
sqrtmult <= 0;
else if (reg_data_collection_idle) begin
if (w_hs && waddr == `ADDR_SQRTMULT)
sqrtmult <= (s_axi_WDATA[7:0] & wmask[7:0]) | (sqrtmult & !wmask[7:0]);
end
end
always @(posedge clk) begin
if (!resetn)
data_source <= 0;

View File

@@ -31,11 +31,15 @@ ADD_LIBRARY( JFJochHLSSimulation STATIC
spot_finder_mask.cpp
save_to_hbm_data.cpp
eiger_reorder.cpp
roi_calc.cpp)
roi_calc.cpp
pixel_sqrt.cpp
HLSDevice.cpp
HLSDevice.h)
TARGET_INCLUDE_DIRECTORIES(JFJochHLSSimulation PUBLIC ../include)
TARGET_LINK_LIBRARIES(JFJochHLSSimulation JFJochCommon)
TARGET_COMPILE_DEFINITIONS(JFJochHLSSimulation PUBLIC -DJFJOCH_HLS_NOSYNTH)
TARGET_INCLUDE_DIRECTORIES(JFJochHLSSimulation PUBLIC ../include)
ADD_EXECUTABLE(frame_summation_tb frame_summation_tb.cpp)
TARGET_LINK_LIBRARIES(frame_summation_tb JFJochHLSSimulation)
@@ -54,55 +58,69 @@ TARGET_LINK_LIBRARIES(adu_histo_tb JFJochHLSSimulation)
IF(VIVADO_HLS)
IF(NOT HLS_SOLUTION_NAME)
SET(HLS_SOLUTION_NAME base1)
ENDIF()
GET_FILENAME_COMPONENT(VITIS_HLS_DIR ${VIVADO_HLS} DIRECTORY)
FIND_FILE(HLS_MATH_H hls_math.h HINT ${VITIS_HLS_DIR}/../include)
IF (HLS_MATH_H)
GET_FILENAME_COMPONENT(VITIS_HLS_INCLUDE_DIR ${HLS_MATH_H} DIRECTORY)
MESSAGE(STATUS "Xilinx HLS headers included")
SET (HLS_IPS "")
#TARGET_INCLUDE_DIRECTORIES(JFJochHLSSimulation PUBLIC ${VITIS_HLS_INCLUDE_DIR})
#TARGET_COMPILE_DEFINITIONS(JFJochHLSSimulation PUBLIC JFJOCH_USE_HLS_HEADERS)
ELSE()
MESSAGE(WARNING "Xilinx HLS headers missing")
#TARGET_INCLUDE_DIRECTORIES(JFJochHLSSimulation PUBLIC ../include)
ENDIF()
FUNCTION( MAKE_HLS_MODULE FUNCTION_NAME SRC_FILE TB_FILE)
ADD_CUSTOM_COMMAND(OUTPUT psi_ch_hls_${FUNCTION_NAME}_1_0.zip
COMMAND ${CMAKE_COMMAND} -E env SRC_DIR=${CMAKE_CURRENT_SOURCE_DIR} HLS_FILE=${SRC_FILE} HLS_TOP_FUNCTION=${FUNCTION_NAME} HLS_TB_FILE=${TB_FILE} ${VIVADO_HLS} -f ${CMAKE_CURRENT_SOURCE_DIR}/../scripts/synth_hls_function.tcl > hls_${FUNCTION_NAME}.log
COMMAND ${CMAKE_COMMAND} -E env HLS_DIR=${CMAKE_CURRENT_BINARY_DIR}/${FUNCTION_NAME}/solution1 CURR_DIR=${CMAKE_CURRENT_BINARY_DIR} bash ${CMAKE_CURRENT_SOURCE_DIR}/../scripts/check_hls.sh ${FUNCTION_NAME}
COMMAND ${CMAKE_COMMAND} -E copy ${FUNCTION_NAME}/solution1/impl/ip/psi_ch_hls_${FUNCTION_NAME}_1_0.zip .
DEPENDS ${SRC_FILE} hls_jfjoch.h ../pcie_driver/jfjoch_fpga.h)
SET (HLS_IPS ${HLS_IPS} psi_ch_hls_${FUNCTION_NAME}_1_0.zip PARENT_SCOPE)
ENDFUNCTION(MAKE_HLS_MODULE)
IF(NOT HLS_SOLUTION_NAME)
SET(HLS_SOLUTION_NAME base1)
ENDIF()
MAKE_HLS_MODULE(data_collection_fsm data_collection_fsm.cpp "")
MAKE_HLS_MODULE(timer_host timer.cpp "")
MAKE_HLS_MODULE(jf_conversion jf_conversion.cpp "")
MAKE_HLS_MODULE(load_calibration load_calibration.cpp "")
MAKE_HLS_MODULE(host_writer host_writer.cpp "")
MAKE_HLS_MODULE(icmp icmp.cpp "")
MAKE_HLS_MODULE(ipv4 ipv4.cpp "")
MAKE_HLS_MODULE(ethernet ethernet.cpp "")
MAKE_HLS_MODULE(arp arp.cpp "")
MAKE_HLS_MODULE(udp udp.cpp "")
MAKE_HLS_MODULE(sls_detector sls_detector.cpp "")
MAKE_HLS_MODULE(frame_generator frame_generator.cpp "")
MAKE_HLS_MODULE(stream_merge stream_merge.cpp "")
MAKE_HLS_MODULE(load_from_hbm load_from_hbm.cpp "")
MAKE_HLS_MODULE(save_to_hbm save_to_hbm.cpp "")
MAKE_HLS_MODULE(save_to_hbm_data save_to_hbm_data.cpp "")
MAKE_HLS_MODULE(mask_missing mask_missing.cpp "")
MAKE_HLS_MODULE(integration integration.cpp integration_tb.cpp)
MAKE_HLS_MODULE(spot_finder spot_finder.cpp spot_finder_tb.cpp)
MAKE_HLS_MODULE(axis_broadcast axis_broadcast.cpp "")
MAKE_HLS_MODULE(axis_64_to_512 axis_helpers.cpp "")
MAKE_HLS_MODULE(axis_32_to_512 axis_helpers.cpp "")
MAKE_HLS_MODULE(adu_histo adu_histo.cpp adu_histo_tb.cpp)
MAKE_HLS_MODULE(pedestal pedestal.cpp "")
MAKE_HLS_MODULE(frame_summation frame_summation.cpp frame_summation_tb_2.cpp)
MAKE_HLS_MODULE(frame_summation_reorder_compl frame_summation_reorder_compl.cpp "")
MAKE_HLS_MODULE(stream_24bit_conv stream_24bit_conv.cpp stream_24bit_conv_tb.cpp)
MAKE_HLS_MODULE(spot_finder_mask spot_finder_mask.cpp "")
MAKE_HLS_MODULE(spot_finder_merge spot_finder_merge.cpp "")
MAKE_HLS_MODULE(spot_finder_connectivity spot_finder_connectivity.cpp "")
MAKE_HLS_MODULE(eiger_reorder eiger_reorder.cpp "")
MAKE_HLS_MODULE(roi_calc roi_calc.cpp "")
SET (HLS_IPS "")
SET (HLS_IPS ${HLS_IPS} PARENT_SCOPE)
ADD_CUSTOM_TARGET(hls DEPENDS ${HLS_IPS})
FUNCTION( MAKE_HLS_MODULE FUNCTION_NAME SRC_FILE TB_FILE)
ADD_CUSTOM_COMMAND(OUTPUT psi_ch_hls_${FUNCTION_NAME}_1_0.zip
COMMAND ${CMAKE_COMMAND} -E env SRC_DIR=${CMAKE_CURRENT_SOURCE_DIR} HLS_FILE=${SRC_FILE} HLS_TOP_FUNCTION=${FUNCTION_NAME} HLS_TB_FILE=${TB_FILE} ${VIVADO_HLS} -f ${CMAKE_CURRENT_SOURCE_DIR}/../scripts/synth_hls_function.tcl > hls_${FUNCTION_NAME}.log
COMMAND ${CMAKE_COMMAND} -E env HLS_DIR=${CMAKE_CURRENT_BINARY_DIR}/${FUNCTION_NAME}/solution1 CURR_DIR=${CMAKE_CURRENT_BINARY_DIR} bash ${CMAKE_CURRENT_SOURCE_DIR}/../scripts/check_hls.sh ${FUNCTION_NAME}
COMMAND ${CMAKE_COMMAND} -E copy ${FUNCTION_NAME}/solution1/impl/ip/psi_ch_hls_${FUNCTION_NAME}_1_0.zip .
DEPENDS ${SRC_FILE} hls_jfjoch.h ../pcie_driver/jfjoch_fpga.h)
SET (HLS_IPS ${HLS_IPS} psi_ch_hls_${FUNCTION_NAME}_1_0.zip PARENT_SCOPE)
ENDFUNCTION(MAKE_HLS_MODULE)
MAKE_HLS_MODULE(data_collection_fsm data_collection_fsm.cpp "")
MAKE_HLS_MODULE(timer_host timer.cpp "")
MAKE_HLS_MODULE(jf_conversion jf_conversion.cpp "")
MAKE_HLS_MODULE(load_calibration load_calibration.cpp "")
MAKE_HLS_MODULE(host_writer host_writer.cpp "")
MAKE_HLS_MODULE(pixel_sqrt pixel_sqrt.cpp pixel_sqrt_tb.cpp)
MAKE_HLS_MODULE(icmp icmp.cpp "")
MAKE_HLS_MODULE(ipv4 ipv4.cpp "")
MAKE_HLS_MODULE(ethernet ethernet.cpp "")
MAKE_HLS_MODULE(arp arp.cpp "")
MAKE_HLS_MODULE(udp udp.cpp "")
MAKE_HLS_MODULE(sls_detector sls_detector.cpp "")
MAKE_HLS_MODULE(frame_generator frame_generator.cpp "")
MAKE_HLS_MODULE(stream_merge stream_merge.cpp "")
MAKE_HLS_MODULE(load_from_hbm load_from_hbm.cpp "")
MAKE_HLS_MODULE(save_to_hbm save_to_hbm.cpp "")
MAKE_HLS_MODULE(save_to_hbm_data save_to_hbm_data.cpp "")
MAKE_HLS_MODULE(mask_missing mask_missing.cpp "")
MAKE_HLS_MODULE(integration integration.cpp integration_tb.cpp)
MAKE_HLS_MODULE(spot_finder spot_finder.cpp spot_finder_tb.cpp)
MAKE_HLS_MODULE(axis_broadcast axis_broadcast.cpp "")
MAKE_HLS_MODULE(axis_64_to_512 axis_helpers.cpp "")
MAKE_HLS_MODULE(axis_32_to_512 axis_helpers.cpp "")
MAKE_HLS_MODULE(adu_histo adu_histo.cpp adu_histo_tb.cpp)
MAKE_HLS_MODULE(pedestal pedestal.cpp "")
MAKE_HLS_MODULE(frame_summation frame_summation.cpp frame_summation_tb_2.cpp)
MAKE_HLS_MODULE(frame_summation_reorder_compl frame_summation_reorder_compl.cpp "")
MAKE_HLS_MODULE(stream_24bit_conv stream_24bit_conv.cpp stream_24bit_conv_tb.cpp)
MAKE_HLS_MODULE(spot_finder_mask spot_finder_mask.cpp "")
MAKE_HLS_MODULE(spot_finder_merge spot_finder_merge.cpp "")
MAKE_HLS_MODULE(spot_finder_connectivity spot_finder_connectivity.cpp "")
MAKE_HLS_MODULE(eiger_reorder eiger_reorder.cpp "")
MAKE_HLS_MODULE(roi_calc roi_calc.cpp "")
SET (HLS_IPS ${HLS_IPS} PARENT_SCOPE)
ADD_CUSTOM_TARGET(hls DEPENDS ${HLS_IPS})
ENDIF()

791
fpga/hls/HLSDevice.cpp Normal file
View File

@@ -0,0 +1,791 @@
// Copyright (2019-2024) Paul Scherrer Institute
#include <future>
#include <bitset>
#include <arpa/inet.h>
#include "HLSDevice.h"
#include "hls_jfjoch.h"
#include "datamover_model.h"
#include "../../jungfrau/sls_packet.h"
#include "../../common/Logger.h"
#include "../../common/JFJochException.h"
struct HLSDeviceImpl {
AXI_STREAM din_eth;
AXI_STREAM din_frame_generator;
AXI_STREAM dout_eth;
constexpr static const size_t hbm_if_count = 32;
constexpr static const size_t hbm_if_size = 32 * 1024 * 1024LU;
ap_uint<2> data_source = STREAM_MERGE_SRC_NETWORK;
std::vector<ap_uint<256>> hbm;
hls::stream<ap_uint<32> > work_request_stream;
hls::stream<ap_uint<32> > completion_stream;
Datamover<512> datamover_in;
Datamover<512> datamover_out;
Datamover<256> datamover_in_hbm_0;
Datamover<256> datamover_in_hbm_1;
Datamover<256, 16> datamover_out_hbm_0;
Datamover<256, 16> datamover_out_hbm_1;
ap_uint<1> run_data_collection;
ap_uint<1> cancel_data_collection;
volatile ap_uint<1> host_writer_idle;
HLSDeviceImpl()
: hbm(hbm_if_size / 32 * hbm_if_count),
datamover_in(Direction::Input, nullptr),
datamover_out(Direction::Output, nullptr),
datamover_out_hbm_0(Direction::Output, (char *) hbm.data()),
datamover_out_hbm_1(Direction::Output, (char *) hbm.data()),
datamover_in_hbm_0(Direction::Input, (char *) hbm.data()),
datamover_in_hbm_1(Direction::Input, (char *) hbm.data()) {}
};
uint16_t checksum(const uint16_t *addr, size_t count) {
/* Compute Internet Checksum for "count" bytes
* beginning at location "addr".
*/
long sum = 0;
for (int i = 0; i < count / 2; i++)
sum += addr[i];
/* Add left-over byte, if any */
if (count % 2 == 1)
sum += ((uint8_t *) addr)[count / 2];
/* Fold 32-bit sum to 16 bits */
while (sum>>16)
sum = (sum & 0xffff) + (sum >> 16);
return ~sum;
}
HLSDevice::HLSDevice(std::vector<DeviceOutput *> &buffer_device) : idle(true), dma_address_table(65536) {
impl_ = std::make_unique<HLSDeviceImpl>();
auto in_mem_location32 = (uint32_t *) dma_address_table.data();
for (int i = 0; i < buffer_device.size(); i++) {
in_mem_location32[2 * i ] = ((uint64_t) buffer_device[i]) & UINT32_MAX;
in_mem_location32[2 * i + 1] = ((uint64_t) buffer_device[i]) >> 32;
}
}
HLSDevice::~HLSDevice() {
if (action_thread.joinable())
action_thread.join();
impl_.reset();
}
void HLSDevice::CreateFinalPacket(const DiffractionExperiment& experiment) {
CreateJFPacket(experiment, UINT64_MAX, 0, 0, nullptr, false);
}
void HLSDevice::SendPacket(char *buffer, int len, uint8_t user) {
auto obuff = (ap_uint<512> *)buffer;
for (int i = 0; i < (len + 63) / 64; i++) {
packet_512_t packet_in;
if (i == (len + 63) / 64 - 1) packet_in.last = 1;
else packet_in.last = 0;
packet_in.keep = 0xFFFFFFFFFFFFFFFF;
packet_in.user = user;
packet_in.data = obuff[i];
impl_->din_eth.write(packet_in);
}
}
void HLSDevice::CreateJFPacket(const DiffractionExperiment& experiment, uint64_t frame_number, uint32_t eth_packet,
uint32_t module_number, const uint16_t *data, int8_t adjust_axis, uint8_t user) {
char buff[256*64];
memset(buff, 0, 256*64);
auto packet = (jf_raw_packet *)buff;
packet->ether_type = htons(0x0800);
packet->sour_mac[0] = 0x00; // module 0
uint64_t tmp_mac = mac_addr;
for (int i = 0; i < 6; i++)
packet->dest_mac[i] = (tmp_mac >> (8*i)) % 256;
uint32_t half_module = 2 * module_number | ((eth_packet >= 64) ? 1 : 0);
packet->ipv4_header_h = htons(0x4500); // Big endian in IP header!
packet->ipv4_header_total_length = htons(8268); // Big endian in IP header!
packet->ipv4_header_dest_ip = ipv4_addr;
packet->ipv4_header_sour_ip = experiment.GetSrcIPv4Address(0, half_module);
packet->ipv4_header_ttl_protocol = htons(0x0011);
packet->ipv4_header_checksum = checksum( (uint16_t *) &packet->ipv4_header_h, 20); // checksum is already in network order
packet->udp_dest_port = htons(234); // port doesn't matter
packet->udp_sour_port = htons(0xDFAC);
packet->udp_length = htons(8248);
// JF headers are little endian
packet->jf.detectortype = SLS_DETECTOR_TYPE_JUNGFRAU;
packet->jf.timestamp = 0xABCDEF0000FEDCBAL;
packet->jf.bunchid = 0x1234567898765431L;
packet->jf.row = half_module;
packet->jf.column = 0;
packet->jf.framenum = frame_number;
packet->jf.packetnum = eth_packet % 64;
if (data != nullptr) {
for (int i = 0; i < 4096; i++)
packet->jf.data[i] = data[i];
}
packet->udp_checksum = htons(checksum( (uint16_t *) (buff+42), 8192+48));
SendPacket(buff, (130+adjust_axis)*64, user);
}
void HLSDevice::CreateJFPackets(const DiffractionExperiment& experiment, uint64_t frame_number_0, uint64_t frames,
uint32_t module_number, const uint16_t *data) {
for (uint64_t i = 0; i < frames; i++) {
for (int j = 0; j < 128; j++)
CreateJFPacket(experiment, frame_number_0 + i, j, module_number, data + (i * 128 + j) * 4096, 0, 0);
}
}
void HLSDevice::CreateEIGERPacket(const DiffractionExperiment &experiment, uint64_t frame_number,
uint32_t eth_packet, uint32_t module_number, uint32_t col, uint32_t row,
const uint16_t *data) {
char buff[256*64];
memset(buff, 0, 256*64);
auto packet = (eiger_raw_packet *)buff;
packet->ether_type = htons(0x0800);
packet->sour_mac[0] = 0x00; // module 0
uint64_t tmp_mac = mac_addr;
for (int i = 0; i < 6; i++)
packet->dest_mac[i] = (tmp_mac >> (8*i)) % 256;
packet->ipv4_header_h = htons(0x4500); // Big endian in IP header!
packet->ipv4_header_total_length = htons(4172); // Big endian in IP header!
packet->ipv4_header_dest_ip = ipv4_addr;
packet->ipv4_header_sour_ip = experiment.GetSrcIPv4Address(0, 0);
packet->ipv4_header_ttl_protocol = htons(0x0011);
packet->ipv4_header_checksum = checksum( (uint16_t *) &packet->ipv4_header_h, 20); // checksum is already in network order
packet->udp_dest_port = htons(234); // ignored
packet->udp_sour_port = htons(0xDFAC);
packet->udp_length = htons(4152);
// JF headers are little endian
packet->eiger.detectortype = SLS_DETECTOR_TYPE_EIGER;
packet->eiger.timestamp = 0xABCDEF0000FEDCBAL;
packet->eiger.bunchid = 0x1234567898765431L;
packet->eiger.row = (2 * module_number) | (row % 2);
packet->eiger.column = col % 2;
packet->eiger.framenum = frame_number;
packet->eiger.packetnum = eth_packet % 64;
if (data != nullptr) {
for (int i = 0; i < 2048; i++)
packet->eiger.data[i] = data[i];
}
packet->udp_checksum = htons(checksum( (uint16_t *) (buff+42), 4096+48));
SendPacket(buff, 66*64, 0);
}
void HLSDevice::HW_ReadActionRegister(DataCollectionConfig *job) {
memcpy(job, &cfg, sizeof(DataCollectionConfig));
}
void HLSDevice::HW_WriteActionRegister(const DataCollectionConfig *job) {
memcpy(&cfg, job, sizeof(DataCollectionConfig));
}
void HLSDevice::FPGA_StartAction(const DiffractionExperiment &experiment) {
if (action_thread.joinable())
action_thread.join();
run_counter += 1;
impl_->run_data_collection = 1;
impl_->cancel_data_collection = 0;
idle = false;
while (!impl_->din_frame_generator.empty())
impl_->din_frame_generator.read();
impl_->datamover_out.ClearCompletedDescriptors();
action_thread = std::thread(&HLSDevice::HLSMainThread, this );
}
void HLSDevice::FrameGeneratorFuture(FrameGeneratorConfig config) {
frame_generator(impl_->din_frame_generator,
impl_->hbm.data(),
impl_->hbm.data(),
impl_->hbm_if_size,
mac_addr,
ipv4_addr,
impl_->cancel_data_collection,
config);
}
void HLSDevice::HW_RunInternalGenerator(const FrameGeneratorConfig &config) {
frame_generator_future = std::async(std::launch::async, &HLSDevice::FrameGeneratorFuture, this, config);
}
void HLSDevice::FPGA_EndAction() {
if (action_thread.joinable())
action_thread.join();
}
bool HLSDevice::HW_ReadMailbox(uint32_t *values) {
std::unique_lock<std::mutex> ul(completion_mutex);
ap_uint<32> tmp;
bool ret = impl_->completion_stream.read_nb(tmp);
values[0] = tmp;
// equivalent to driver functionality
if (ret) {
uint32_t data_collection_id = (values[0] >> 16) & 0xFFFF;
uint32_t handle = values[0] & 0xFFFF;
if (handle == HANDLE_START)
completion_count = 0;
else if ((handle != HANDLE_END) && (data_collection_id != DATA_COLLECTION_ID_PURGE)) {
completion_count++;
while (completion_count * DMA_DESCRIPTORS_PER_MODULE > impl_->datamover_out.GetCompletedDescriptors())
std::this_thread::sleep_for(std::chrono::milliseconds(1));
}
}
return ret;
}
void HLSDevice::Cancel() {
impl_->cancel_data_collection = 1;
}
bool HLSDevice::HW_IsIdle() const {
return idle && impl_->datamover_out.IsIdle();
}
bool HLSDevice::HW_SendWorkRequest(uint32_t handle) {
impl_->work_request_stream.write(handle);
return true;
}
inline uint32_t float2uint(float f) {
float_uint32 fu;
fu.f = f;
return fu.u;
}
void HLSDevice::HLSMainThread() {
ap_uint<1> clear_counters = 0;
uint64_t packets_processed;
std::vector<std::thread> hls_cores;
STREAM_512 ip1, udp1, udp2, icmp1, arp1;
STREAM_512 network0;
STREAM_768 stream_768_0;
STREAM_768 stream_768_1;
STREAM_768 stream_768_2;
STREAM_768 stream_768_3;
STREAM_768 stream_768_4;
STREAM_768 stream_768_5;
STREAM_768 stream_768_6;
STREAM_512 data_0;
hls::stream<ap_axiu<512, 1, 1, 1>, 2> data_1;
hls::stream<ap_axiu<512, 1, 1, 1>, 2> data_2;
STREAM_512 data_3;
STREAM_512 data_4;
STREAM_512 data_5;
STREAM_512 data_6;
STREAM_512 data_7;
STREAM_512 data_8;
STREAM_512 data_9;
STREAM_512 data_10;
STREAM_512 data_12;
STREAM_512 data_13;
hls::stream<axis_addr> addr0;
hls::stream<axis_addr> addr1;
hls::stream<axis_addr> addr2;
hls::stream<axis_addr> addr3;
hls::stream<axis_completion> axi_compl[12];
hls::stream<ap_uint<16>> hbm_handles;
hls::stream<ap_uint<512>> adu_histo_result;
hls::stream<ap_axiu<64,1,1,1>> integration_result_0;
hls::stream<ap_uint<512>> integration_result_1;
hls::stream<ap_axiu<32,1,1,1>> spot_finder_result_0;
hls::stream<ap_axiu<32,1,1,1>> spot_finder_result_1;
hls::stream<ap_uint<32>> spot_finder_conn_0;
hls::stream<ap_axiu<32,1,1,1>> spot_finder_result_2;
hls::stream<ap_uint<512>> spot_finder_result_3;
hls::stream<ap_uint<32>> spot_finder_mask_0;
hls::stream<ap_uint<256>> roi_calc_result_0;
hls::stream<ap_uint<UDP_METADATA_STREAM_WIDTH> > udp_metadata;
volatile ap_uint<1> idle_data_collection = 1;
ap_uint<1> load_to_hbm_idle;
ap_uint<1> save_to_hbm_idle;
ap_uint<1> integration_idle;
ap_uint<1> stream_conv_idle;
ap_uint<1> frame_summation_idle;
volatile bool done = false;
volatile bool udp_done = false; // done AND udp_idle
volatile bool sls_done = false; // done AND sls_idle
// Sent gratuitous ARP message
arp(arp1, impl_->dout_eth, mac_addr, ipv4_addr, 1, 1);
Logger logger_hls("HLS");
volatile rcv_state_t state = RCV_INIT;
// Start data collection
data_collection_fsm(data_0, data_1,
addr0, addr1,
impl_->run_data_collection,
impl_->cancel_data_collection,
idle_data_collection,
cfg.mode,
float2uint(cfg.energy_kev),
cfg.nframes,
cfg.nmodules,
cfg.nstorage_cells,
cfg.nsummation ,
cfg.sqrtmult, state);
impl_->run_data_collection = 0;
data_collection_fsm(data_0, data_1,
addr0, addr1,
impl_->run_data_collection,
impl_->cancel_data_collection,
idle_data_collection,
cfg.mode,
float2uint(cfg.energy_kev),
cfg.nframes,
cfg.nmodules,
cfg.nstorage_cells,
cfg.nsummation,
cfg.sqrtmult,
state);
hls_cores.emplace_back([&] {
while (!udp_done) {
if (impl_->din_eth.empty() && impl_->din_frame_generator.empty())
std::this_thread::sleep_for(std::chrono::microseconds(10));
else
stream_merge(impl_->din_eth, impl_->din_frame_generator, network0, impl_->data_source);
}
logger_hls.Info("Stream_merge done");
});
hls_cores.emplace_back([&] {
while (!udp_done) {
if (network0.empty())
std::this_thread::sleep_for(std::chrono::microseconds(10));
else
ethernet(network0, ip1, arp1, mac_addr, eth_packets, clear_counters);
}
logger_hls.Info("ethernet done");
});
hls_cores.emplace_back([&] {
while (!udp_done) {
if (ip1.empty())
std::this_thread::sleep_for(std::chrono::microseconds(10));
else
ipv4(ip1, udp1, icmp1, ipv4_addr);
}
logger_hls.Info("ipv4 done");
});
hls_cores.emplace_back([&] {
ap_uint<1> udp_idle = 1;
while (!done || !udp_idle) {
if (udp1.empty())
std::this_thread::sleep_for(std::chrono::microseconds(10));
else
udp(udp1, udp2, udp_metadata, udp_packets, clear_counters, udp_idle);
}
udp_done = true;
logger_hls.Info("udp done");
});
hls_cores.emplace_back([&] {
ap_uint<1> sls_idle = 1;
while (!done || !sls_idle) {
if (udp2.empty())
std::this_thread::sleep_for(std::chrono::microseconds (10));
else
sls_detector(udp2, udp_metadata, data_0, addr0, sls_packets, udp_eth_err, udp_len_err, current_pulse_id,
clear_counters, sls_idle);
}
sls_done = true;
logger_hls.Info("sls_detector done");
});
// 1. Parse incoming UDP packets
hls_cores.emplace_back([&] {
while ((state != RCV_WAIT_FOR_START) || (idle_data_collection.read() == 0) || (!data_0.empty())) {
data_collection_fsm(data_0, data_1,
addr0, addr1,
impl_->run_data_collection,
impl_->cancel_data_collection,
idle_data_collection,
cfg.mode,
float2uint(cfg.energy_kev),
cfg.nframes,
cfg.nmodules,
cfg.nstorage_cells,
cfg.nsummation,
cfg.sqrtmult,
state);
}
done = true;
logger_hls.Info("data collection done");
});
// 2. Cache images in HBM
hls_cores.emplace_back([&] { save_to_hbm(addr1, axi_compl[0], hbm_handles,
impl_->datamover_out_hbm_0.GetCtrlStream(),
impl_->datamover_out_hbm_1.GetCtrlStream(),
save_to_hbm_idle,
impl_->hbm_if_size);});
hls_cores.emplace_back([&] { save_to_hbm_data(data_1,
data_3,
impl_->datamover_out_hbm_0.GetDataStream(),
impl_->datamover_out_hbm_1.GetDataStream());});
hls_cores.emplace_back([&] {frame_summation_reorder_compl(data_3, data_4, axi_compl[0], axi_compl[1]);});
hls_cores.emplace_back([&] { load_from_hbm(data_4, data_5, axi_compl[1], axi_compl[2], hbm_handles,
impl_->datamover_in_hbm_0.GetDataStream(), impl_->datamover_in_hbm_1.GetDataStream(),
impl_->datamover_in_hbm_0.GetCtrlStream(), impl_->datamover_in_hbm_1.GetCtrlStream(),
load_to_hbm_idle, impl_->hbm_if_size);});
hls_cores.emplace_back([&] { pedestal(data_5, data_6, axi_compl[2], axi_compl[3],
impl_->hbm.data(),
impl_->hbm.data(),
impl_->hbm.data(),
impl_->hbm.data(),
impl_->hbm.data(),
impl_->hbm.data(),
impl_->hbm.data(),
impl_->hbm.data(),
impl_->hbm.data(),
impl_->hbm.data(),
impl_->hbm.data(),
impl_->hbm.data(),
impl_->hbm_if_size);});
// 3. Calculate histogram of ADU values
hls_cores.emplace_back([&] { adu_histo(data_6, data_7, adu_histo_result, axi_compl[3], axi_compl[4]);});
// 4. Mask missing pixels
hls_cores.emplace_back([&] { mask_missing(data_7, data_8, axi_compl[4], axi_compl[5]);});
// 5. Handle EIGER packets properly
hls_cores.emplace_back([&] { eiger_reorder(data_8, data_9, axi_compl[5], axi_compl[6]);});
// 6. Apply pedestal & gain corrections
hls_cores.emplace_back([&] { jf_conversion(data_9, stream_768_0,
axi_compl[6], axi_compl[7],
impl_->hbm.data(),
impl_->hbm.data(),
impl_->hbm.data(),
impl_->hbm.data(),
impl_->hbm.data(),
impl_->hbm.data(),
impl_->hbm.data(),
impl_->hbm.data(),
impl_->hbm.data(),
impl_->hbm.data(),
impl_->hbm.data(),
impl_->hbm.data(),
impl_->hbm_if_size); });
// 7. Frame summation
hls_cores.emplace_back([&] { frame_summation(stream_768_0, stream_768_1, axi_compl[7], axi_compl[8], frame_summation_idle);});
// 8. Integration of pixels
hls_cores.emplace_back([&] { integration(stream_768_1, stream_768_2, integration_result_0, axi_compl[8], axi_compl[9],
impl_->hbm.data(), impl_->hbm.data(), impl_->hbm.data(), impl_->hbm.data(), integration_idle, impl_->hbm_if_size);});
hls_cores.emplace_back([&] { axis_64_to_512(integration_result_0, integration_result_1);});
// 9. Spot finding
ap_uint<32> tmp_snr_threshold = float2uint(spot_finder_parameters.snr_threshold);
ap_uint<32> min_d = float2uint(spot_finder_parameters.min_d);
ap_uint<32> max_d = float2uint(spot_finder_parameters.max_d);
ap_int<32> tmp_count_threshold = spot_finder_parameters.count_threshold;
ap_uint<32> min_pix_per_spot = spot_finder_parameters.min_pix_per_spot;
hls_cores.emplace_back([&] {
spot_finder_mask(stream_768_2,
stream_768_3,
spot_finder_mask_0,
axi_compl[9],
axi_compl[10],
impl_->hbm.data(),
impl_->hbm.data(),
min_d,
max_d,
impl_->hbm_if_size);
logger_hls.Info("spot_finder_mask done");
});
hls_cores.emplace_back([&] {
spot_finder(stream_768_3, spot_finder_mask_0, stream_768_4, spot_finder_result_0, tmp_count_threshold, tmp_snr_threshold);
logger_hls.Info("spot_finder done");
});
hls_cores.emplace_back([&] {
spot_finder_connectivity(spot_finder_result_0,
spot_finder_result_1,
spot_finder_conn_0);
logger_hls.Info("spot_finder_connectivity done");
});
hls_cores.emplace_back([&] {
spot_finder_merge(spot_finder_result_1,
spot_finder_conn_0,
spot_finder_result_2,
min_pix_per_spot);
logger_hls.Info("spot_finder_merge done");
});
hls_cores.emplace_back([&] {
axis_32_to_512(spot_finder_result_2, spot_finder_result_3);
logger_hls.Info("axis_32_to_512 done");
});
// 10. ROI calculation
hls_cores.emplace_back([&] {
roi_calc(stream_768_4,
stream_768_5,
roi_calc_result_0,
axi_compl[10],
axi_compl[11],
impl_->hbm.data(),
impl_->hbm.data(),
impl_->hbm_if_size);
logger_hls.Info("roi_calc done");
});
// 11. Pixel sq root
hls_cores.emplace_back([&] {
pixel_sqrt(stream_768_5,
stream_768_6);
logger_hls.Info("pixel_sqrt done");
});
// 12. Reduce/extend 24-bit stream
hls_cores.emplace_back([&] { stream_24bit_conv(stream_768_6, data_12, stream_conv_idle);});
// 13. Prepare data to write to host memory
hls_cores.emplace_back([&] {
ap_uint<3> state;
host_writer(data_12, adu_histo_result, integration_result_1, spot_finder_result_3, roi_calc_result_0,
axi_compl[11], impl_->datamover_out.GetDataStream(),
impl_->datamover_out.GetCtrlStream(), impl_->work_request_stream, impl_->completion_stream,
dma_address_table.data(), packets_processed, impl_->host_writer_idle, impl_->cancel_data_collection, state);
logger_hls.Info("host_writer done");
});
for (auto &i : hls_cores)
i.join();
if (frame_generator_future.valid())
frame_generator_future.get();
// reset static counter
arp(arp1, impl_->dout_eth, mac_addr, ipv4_addr, 0, 1);
try {
while (!impl_->din_eth.empty())
impl_->din_eth.read();
if (!addr1.empty())
throw std::runtime_error("Addr1 queue not empty");
if (!addr2.empty())
throw std::runtime_error("Addr2 queue not empty");
if (!addr3.empty())
throw std::runtime_error("Addr3 queue not empty");
if (!data_1.empty())
throw std::runtime_error("data_1 queue not empty");
if (!data_2.empty())
throw std::runtime_error("data_2 queue not empty");
if (!data_3.empty())
throw std::runtime_error("data_3 queue not empty");
if (!data_4.empty())
throw std::runtime_error("data_4 queue not empty");
if (!data_5.empty())
throw std::runtime_error("data_5 queue not empty");
if (!data_7.empty())
throw std::runtime_error("data_7 queue not empty");
if (!data_8.empty())
throw std::runtime_error("data_8 queue not empty");
if (!data_9.empty())
throw std::runtime_error("data_9 queue not empty");
if (!data_10.empty())
throw std::runtime_error("data_10 queue not empty");
if (!data_12.empty())
throw std::runtime_error("data_12 queue not empty");
if (!data_13.empty())
throw std::runtime_error("data_13 queue not empty");
for (auto &c: axi_compl) {
if (!c.empty())
throw std::runtime_error("Compl queue not empty");
}
if (!stream_768_0.empty())
throw std::runtime_error("stream_768_0 queue not empty");
if (!stream_768_1.empty())
throw std::runtime_error("stream_768_1 queue not empty");
if (!stream_768_2.empty())
throw std::runtime_error("stream_768_2 queue not empty");
if (!stream_768_3.empty())
throw std::runtime_error("stream_768_3 queue not empty");
if (!stream_768_4.empty())
throw std::runtime_error("stream_768_4 queue not empty");
if (!hbm_handles.empty())
throw std::runtime_error("Handles queue not empty");
if (!integration_result_0.empty())
throw std::runtime_error("Integration result queue not empty");
if (!integration_result_1.empty())
throw std::runtime_error("Integration result queue not empty");
if (!impl_->datamover_in.GetDataStream().empty())
throw std::runtime_error("Datamover queue is not empty");
while (!impl_->datamover_out.IsIdle())
std::this_thread::sleep_for(std::chrono::milliseconds(100));
} catch (const std::runtime_error &e) {
logger_hls.ErrorException(e);
throw e;
}
idle = true;
}
DataCollectionStatus HLSDevice::GetDataCollectionStatus() const {
DataCollectionStatus status{};
union {
uint64_t u64;
double d;
} pulse_id_conv;
pulse_id_conv.u64 = current_pulse_id;
status.ctrl_reg = ap_uint<1>(impl_->host_writer_idle) ? (1 << 4) : 0;
status.max_modules = MAX_MODULES_FPGA;
status.hbm_size_bytes = impl_->hbm_if_size;
status.run_counter = run_counter;
status.current_pulseid = pulse_id_conv.d;
status.packets_udp = udp_packets;
status.packets_eth = eth_packets;
status.packets_sls = sls_packets;
return status;
}
void HLSDevice::HW_LoadCalibration(const LoadCalibrationConfig &config) {
int ret = load_calibration(impl_->hbm.data(), impl_->hbm.data(),
config,
impl_->hbm_if_size,
impl_->datamover_in.GetCtrlStream(),
impl_->datamover_in.GetDataStream(),
dma_address_table.data());
if (ret)
throw JFJochException(JFJochExceptionCategory::AcquisitionDeviceError,
"Error in loading calibration " + std::to_string(ret));
if (!impl_->datamover_in.GetDataStream().empty())
throw std::runtime_error("Datamover queue is not empty");
}
void HLSDevice::HW_SetSpotFinderParameters(const SpotFinderParameters &params) {
spot_finder_parameters = params;
}
void HLSDevice::HW_SetDataSource(uint32_t val) {
impl_->data_source = val;
}
uint32_t HLSDevice::HW_GetDataSource() {
return impl_->data_source;
}
void HLSDevice::CreateXfelBunchIDPacket(double pulse_id, uint32_t event_code) {
union {
uint64_t u64;
double d;
} pulse_id_conv;
pulse_id_conv.d = pulse_id;
bunchid_raw_packet packet{};
packet.ether_type = htons(0x0800);
for (int i = 0; i < 6; i++)
packet.dest_mac[i] = 0xFF;
packet.ipv4_header_h = htons(0x4500); // Big endian in IP header!
packet.ipv4_header_total_length = htons(sizeof(bunchid_payload) + 8 + 20); // Big endian in IP header!
packet.ipv4_header_dest_ip = UINT32_MAX;
packet.ipv4_header_ttl_protocol = htons(0x0011);
packet.ipv4_header_checksum = checksum( (uint16_t *) &packet.ipv4_header_h, 20); // checksum is already in network order
packet.udp_length = htons(sizeof(bunchid_payload) + 8);
packet.payload.magicn[0] = BUNCHID_MAGICN;
packet.payload.magicn[1] = BUNCHID_MAGICN;
packet.payload.magicn[2] = BUNCHID_MAGICN;
packet.payload.bunchid_msb[0] = (pulse_id_conv.u64 >> 32) & UINT32_MAX;
packet.payload.bunchid_msb[1] = (pulse_id_conv.u64 >> 32) & UINT32_MAX;
packet.payload.bunchid_lsb[0] = pulse_id_conv.u64 & UINT32_MAX;
packet.payload.bunchid_lsb[1] = pulse_id_conv.u64 & UINT32_MAX;
packet.payload.montrig = event_code;
SendPacket((char *) &packet, sizeof(bunchid_raw_packet));
}

75
fpga/hls/HLSDevice.h Normal file
View File

@@ -0,0 +1,75 @@
// Copyright (2019-2024) Paul Scherrer Institute
#ifndef JFJOCH_HLSDEVICE_H
#define JFJOCH_HLSDEVICE_H
#include <future>
#include "../../common/DiffractionExperiment.h"
#include "../pcie_driver/jfjoch_fpga.h"
class HLSDeviceImpl;
class HLSDevice {
// Hide all HLS simulation structures here
std::unique_ptr<HLSDeviceImpl> impl_;
std::mutex completion_mutex;
uint32_t completion_count;
std::thread action_thread;
std::future<void> frame_generator_future;
std::vector<uint64_t> dma_address_table;
uint64_t eth_packets = 0;
uint64_t icmp_packets = 0;
uint64_t udp_packets = 0;
uint64_t sls_packets = 0;
uint32_t udp_len_err = 0;
uint32_t udp_eth_err = 0;
uint64_t current_pulse_id = 0;
uint32_t run_counter = 0;
DataCollectionConfig cfg;
SpotFinderParameters spot_finder_parameters;
const uint64_t mac_addr = 0xCCAA11223344;
const uint32_t ipv4_addr = 0x0132010A;
volatile bool idle;
void FrameGeneratorFuture(FrameGeneratorConfig config);
void HLSMainThread();
public:
explicit HLSDevice(std::vector<DeviceOutput *> &device_buffer);
~HLSDevice();
void SendPacket(char *buffer, int len, uint8_t user = 0);
void CreateJFPacket(const DiffractionExperiment& experiment, uint64_t frame_number, uint32_t eth_packet,
uint32_t module_number, const uint16_t *data, int8_t adjust_axis = 0, uint8_t user = 0);
void CreateJFPackets(const DiffractionExperiment& experiment, uint64_t frame_number_0, uint64_t frames,
uint32_t module_number, const uint16_t *data);
void CreateEIGERPacket(const DiffractionExperiment& experiment, uint64_t frame_number, uint32_t eth_packet,
uint32_t module_number, uint32_t col, uint32_t row,
const uint16_t *data);
void CreateFinalPacket(const DiffractionExperiment& experiment);
void CreateXfelBunchIDPacket(double bunchid, uint32_t event_code);
DataCollectionStatus GetDataCollectionStatus() const ;
void Cancel() ;
void HW_ReadActionRegister(DataCollectionConfig *job);
void HW_WriteActionRegister(const DataCollectionConfig *job);
void FPGA_StartAction(const DiffractionExperiment &experiment);
void FPGA_EndAction();
bool HW_IsIdle() const;
bool HW_ReadMailbox(uint32_t *values);
bool HW_SendWorkRequest(uint32_t handle);
void HW_LoadCalibration(const LoadCalibrationConfig &config);
void HW_SetSpotFinderParameters(const SpotFinderParameters &params);
uint32_t HW_GetDataSource();
void HW_SetDataSource(uint32_t val);
void HW_RunInternalGenerator(const FrameGeneratorConfig &config) ;
};
#endif //JFJOCH_HLSDEVICE_H

View File

@@ -36,9 +36,9 @@ int main() {
for (int i = 0; i < nframes * RAW_MODULE_SIZE * sizeof(uint16_t) / 64 + 2; i++)
output.read();
if (adu_result.size() != nframes * (ADU_HISTO_BIN_COUNT / 16))
if (adu_result.size() != nframes * (ADU_HISTO_BIN_COUNT / 16 + 1))
ret = 1;
for (int i = 0; i < nframes * (ADU_HISTO_BIN_COUNT / 16); i++)
for (int i = 0; i < nframes * (ADU_HISTO_BIN_COUNT / 16 + 1); i++)
adu_result.read();
if (compl_out.size() != nframes + 1)

View File

@@ -16,6 +16,7 @@ void data_collection_fsm(AXI_STREAM &eth_in,
ap_uint<5> nmodules,
ap_uint<4> nstorage_cells,
ap_uint<8> nsummation,
ap_uint<8> sqrtmult,
volatile rcv_state_t &data_collection_state) {
#pragma HLS INTERFACE ap_ctrl_none port=return
@@ -33,6 +34,7 @@ void data_collection_fsm(AXI_STREAM &eth_in,
#pragma HLS INTERFACE ap_none register port=nmodules
#pragma HLS INTERFACE ap_none register port=nstorage_cells
#pragma HLS INTERFACE ap_none register port=nsummation
#pragma HLS INTERFACE ap_none register port=sqrtmult
#pragma HLS INTERFACE ap_none register port=data_collection_state
#pragma HLS PIPELINE II=1 style=flp
@@ -78,6 +80,7 @@ void data_collection_fsm(AXI_STREAM &eth_in,
ACT_REG_NMODULES(packet_out.data) = nmodules;
ACT_REG_NSTORAGE_CELLS(packet_out.data) = nstorage_cells + 1;
ACT_REG_NSUMMATION(packet_out.data) = nsummation;
ACT_REG_SQRTMULT(packet_out.data) = sqrtmult;
packet_out.user = 0;
packet_out.last = 1;

View File

@@ -10,17 +10,23 @@
#include <cstring>
#include <hls_burst_maxi.h>
#ifndef __SYNTHESIS__
#define ap_wait()
#endif
#ifndef JFJOCH_HLS_NOSYNTH
#include <ap_axi_sdata.h>
#include <hls_stream.h>
#include <hls_math.h>
#else
#define ap_wait()
#include "parallel_stream.h"
#include <cmath>
namespace hls {
inline bool isfinite(float f) {return std::isfinite(f);}
// inline float sqrt(float f) {return std::sqrt(f); }
template <class T> float sqrt(const T &f) {return std::round(std::sqrt(f.to_float())); }
}
#endif
@@ -61,7 +67,8 @@ typedef hls::stream<packet_768_t> STREAM_768;
#define ACT_REG_NFRAMES(x) ((x)(95 , 64)) // 32 bit
#define ACT_REG_NMODULES(x) ((x)(132, 128)) // 5 bit (0..31)
#define ACT_REG_NSTORAGE_CELLS(x) ((x)(148, 144)) // 5 bit
#define ACT_REG_NSUMMATION(x) ((x)(167, 160)) // 7 bit (0..255)
#define ACT_REG_NSUMMATION(x) ((x)(167, 160)) // 8 bit (0..255)
#define ACT_REG_SQRTMULT(x) ((x)(175, 168)) // 8 bit (0..255)
struct axis_datamover_ctrl {
ap_uint<40+64> data;
@@ -330,6 +337,7 @@ void data_collection_fsm(AXI_STREAM &eth_in,
ap_uint<5> nmodules,
ap_uint<4> nstorage_cells,
ap_uint<8> nsummation,
ap_uint<8> sqrootmult,
volatile rcv_state_t &state);
void host_writer(STREAM_512 &data_in,
@@ -444,4 +452,7 @@ void roi_calc(STREAM_768 &data_in,
ap_uint<256> *d_hbm_p1,
ap_uint<32> hbm_size_bytes);
void pixel_sqrt(STREAM_768 &data_in,
STREAM_768 &data_out);
#endif

47
fpga/hls/pixel_sqrt.cpp Normal file
View File

@@ -0,0 +1,47 @@
// Copyright (2019-2023) Paul Scherrer Institute
#include "hls_jfjoch.h"
void pixel_sqrt(STREAM_768 &data_in,
STREAM_768 &data_out) {
#pragma HLS INTERFACE register both axis port=data_in
#pragma HLS INTERFACE register both axis port=data_out
#pragma HLS INTERFACE ap_ctrl_none port=return
packet_768_t packet_in;
{
#pragma HLS PROTOCOL fixed
data_in >> packet_in;
ap_wait();
data_out << packet_in;
ap_wait();
}
ap_uint<32> data_collection_mode = ACT_REG_MODE(packet_in.data);
ap_uint<1> apply_sqroot = ((data_collection_mode & MODE_SQROOT) ? 1 : 0);
ap_uint<9> sqrtmult = ACT_REG_SQRTMULT(packet_in.data) * ACT_REG_SQRTMULT(packet_in.data);
data_in >> packet_in;
while (!packet_in.user) {
#pragma HLS PIPELINE II=1
if (apply_sqroot) {
ap_int<24> pixel[32];
unpack32(packet_in.data, pixel);
for (int i = 0; i < 32; i++) {
ap_uint<32> tmp = pixel[i] * sqrtmult;
if ((pixel[i] == INT24_MAX) || (pixel[i] == INT24_MIN)) {
pixel[i] = pixel[i];
} else if (pixel[i] < 0)
pixel[i] = 0;
else
pixel[i] = hls::sqrt(tmp);
}
packet_in.data = pack32(pixel);
}
data_out << packet_in;
data_in >> packet_in;
}
data_out << packet_in;
}

View File

@@ -0,0 +1,65 @@
// Copyright (2019-2024) Paul Scherrer Institute
#include "hls_jfjoch.h"
int main() {
bool all_good = true;
std::vector<uint16_t> sqrtmult_values = {1,2,4,8,16};
for (int i = 0; i < sqrtmult_values.size(); i++) {
uint16_t sqrtmult = sqrtmult_values[i];
STREAM_768 input;
STREAM_768 output;
packet_768_t packet_in;
packet_in.user = 0;
packet_in.data = 0;
ACT_REG_SQRTMULT(packet_in.data) = sqrtmult;
ACT_REG_MODE(packet_in.data) = MODE_SQROOT;
input << packet_in;
ap_int<24> values_in[32], values_out[32];
for (int i = 0; i < 30; i++)
values_in[i] = i;
values_in[30] = INT24_MAX;
values_in[31] = INT24_MIN;
packet_in.data = pack32(values_in);
input << packet_in;
input << packet_768_t{.user = 1};
pixel_sqrt(input, output);
output.read();
packet_768_t packet_out = output.read();
output.read();
unpack32(packet_out.data, values_out);
for (int i = 0; i < 32; i++) {
double value_expected = std::round(std::sqrt(values_in[i].to_float()) * sqrtmult);
if (values_in[i] == INT24_MAX)
value_expected = INT24_MAX;
if (values_in[i] == INT24_MIN)
value_expected = INT24_MIN;
if (values_out[i] != value_expected) {
all_good = false;
std::cerr << "Value " << i << " expected: " << value_expected << " calculated " << values_out[i] << " sqrtmult " << sqrtmult << std::endl;
}
}
}
if (all_good)
return 0;
else
return 1;
}

View File

@@ -45,9 +45,10 @@ int main() {
for (int i = 0; i < nframes * RAW_MODULE_SIZE * sizeof(uint16_t) / 64 + 2; i++)
output.read();
if (strong_pixel.size() != nframes * (RAW_MODULE_SIZE * sizeof(uint16_t) / 64 + 2) + 1)
if (strong_pixel.size() != nframes * (RAW_MODULE_SIZE * sizeof(uint16_t) / 64 + 16) + 1) {
ret = 1;
for (int i = 0; i < nframes * (RAW_MODULE_SIZE * sizeof(uint16_t) / 64 + 2) + 1; i++)
}
for (int i = 0; i < nframes * (RAW_MODULE_SIZE * sizeof(uint16_t) / 64 + 16) + 1; i++)
strong_pixel.read();
if (ret != 0) {

View File

@@ -3,5 +3,66 @@
#include "hls_jfjoch.h"
int main() {
bool all_good = true;
STREAM_768 input;
STREAM_512 output;
packet_768_t packet_in;
packet_in.user = 0;
packet_in.data = 0;
ACT_REG_MODE(packet_in.data) = MODE_32BIT;
input << packet_in;
ap_int<24> values_in[32];
ap_int<32> values_out[32];
for (int i = 0; i < 30; i++)
values_in[i] = i;
values_in[30] = INT24_MAX;
values_in[31] = INT24_MIN;
packet_in.data = pack32(values_in);
input << packet_in;
input << packet_768_t{.user = 1};
volatile ap_uint<1> idle;
stream_24bit_conv(input, output, idle);
if (output.size() != 4) {
std::cerr << "Wrong output size" << std::endl;
return 1;
}
output.read();
packet_512_t packet_out_1 = output.read();
packet_512_t packet_out_2 = output.read();
output.read();
ap_uint<1024> packet_out = (packet_out_2.data, packet_out_1.data);
unpack32(packet_out, values_out);
for (int i = 0; i < 32; i++) {
int32_t value_expected = values_in[i];
if (values_in[i] == INT24_MAX)
value_expected = INT32_MAX;
if (values_in[i] == INT24_MIN)
value_expected = INT32_MIN;
if (values_out[i] != value_expected) {
all_good = false;
std::cerr << "Value " << i << " expected: " << value_expected << " calculated " << values_out[i] << std::endl;
}
}
if (all_good)
return 0;
else
return 1;
}

View File

@@ -1,5 +1,5 @@
PACKAGE_NAME=jfjoch
PACKAGE_VERSION=1.0.0
PACKAGE_VERSION=1.0.0-rc.12
DEST_MODULE_LOCATION=/extra
BUILT_MODULE_NAME=jfjoch

View File

@@ -11,7 +11,7 @@
MODULE_AUTHOR("Filip Leonarski; Paul Scherrer Institute");
MODULE_DESCRIPTION("Jungfraujoch device module");
MODULE_LICENSE("GPL");
MODULE_VERSION("1.0.0");
MODULE_VERSION("1.0.0-rc.12");
#define XDMA_GEN4_x8 (0x9048)
#define XDMA_GEN3_x16 (0x903F)

View File

@@ -95,7 +95,7 @@
#define ADDR_ONE_OVER_ENERGY 0x0214
#define ADDR_NFRAMES 0x0218
#define ADDR_NSTORAGE_CELLS 0x021C
#define ADDR_DATA_SOURCE 0x0224
#define ADDR_DATA_SOURCE 0x0300
#define ADDR_SPOT_FINDER_THRESHOLD 0x0100
#define ADDR_SPOT_FINDER_SNR 0x0104

View File

@@ -27,7 +27,7 @@ typedef __u64 uint64_t;
#define GAIN_G2_MULTIPLIER (-1)
#define JFJOCH_FPGA_MAGIC 0x52324158
#define JFJOCH_FPGA_RELEASE 0x0056
#define JFJOCH_FPGA_RELEASE 0x0057
#define JFJOCH_FPGA_VARIANT_100G 0
#define JFJOCH_FPGA_VARIANT_8x10G 1
@@ -35,6 +35,7 @@ typedef __u64 uint64_t;
#define MODE_CONV 0x0001L
#define MODE_32BIT 0x0002L
#define MODE_UNSIGNED 0x0004L
#define MODE_SQROOT 0x0008L
#define MODE_PEDESTAL_G0 0x0010L
#define MODE_PEDESTAL_G1 0x0020L
#define MODE_PEDESTAL_G2 0x0040L
@@ -106,6 +107,7 @@ struct DataCollectionConfig {
uint32_t nframes; // Number of frames for data collection
uint32_t nstorage_cells; // Number of storage cells minus one (0 = 1SC, 1 = 2SC, ..., 15 = 16SC)
uint32_t nsummation; // Summation of frames minus one (0 = no summation, 1 = 2 frames, 2 = 3 frames, ..., 255 = 256 frames)
uint32_t sqrtmult; // Multiplication factor (minus one) of pixel value BEFORE taking square root function - should be square of the coeff used in other work
};
struct DataCollectionStatus {

View File

@@ -1,7 +1,7 @@
#!/bin/bash
# Taken from https://schneide.blog/2015/08/10/packaging-kernel-modulesdrivers-using-dkms/
VERSION="1.0.0"
VERSION=1.0.0-rc.12
occurrences=`/usr/sbin/dkms status | grep jfjoch | grep ${VERSION} | wc -l`

View File

@@ -1,7 +1,7 @@
#!/bin/bash
# Taken from https://schneide.blog/2015/08/10/packaging-kernel-modulesdrivers-using-dkms/
VERSION="1.0.0"
VERSION=1.0.0-rc.12
/usr/sbin/dkms remove -m jfjoch -v ${VERSION} --all

View File

@@ -249,6 +249,12 @@ proc create_hier_cell_image_processing { parentCell nameHier } {
CONFIG.FIFO_DEPTH {512} \
] $axis_data_fifo_10
# Create instance: axis_data_fifo_11, and set properties
set axis_data_fifo_11 [ create_bd_cell -type ip -vlnv xilinx.com:ip:axis_data_fifo:2.0 axis_data_fifo_11 ]
set_property -dict [ list \
CONFIG.FIFO_DEPTH {512} \
] $axis_data_fifo_11
# Create instance: axis_data_spot_finder_mask_0, and set properties
set axis_data_spot_finder_mask_0 [ create_bd_cell -type ip -vlnv xilinx.com:ip:axis_data_fifo:2.0 axis_data_spot_finder_mask_0 ]
set_property -dict [ list \
@@ -343,6 +349,9 @@ proc create_hier_cell_image_processing { parentCell nameHier } {
# Create instance: pedestal_0, and set properties
set pedestal_0 [ create_bd_cell -type ip -vlnv psi.ch:hls:pedestal:1.0 pedestal_0 ]
# Create instance: pixel_sqrt_0, and set properties
set pixel_sqrt_0 [ create_bd_cell -type ip -vlnv psi.ch:hls:pixel_sqrt:1.0 pixel_sqrt_0 ]
# Create instance: roi_calc_0, and set properties
set roi_calc_0 [ create_bd_cell -type ip -vlnv psi.ch:hls:roi_calc:1.0 roi_calc_0 ]
@@ -414,7 +423,8 @@ proc create_hier_cell_image_processing { parentCell nameHier } {
connect_bd_intf_net -intf_net axis_compl_fifo_6_M_AXIS [get_bd_intf_pins axis_compl_fifo_6/M_AXIS] [get_bd_intf_pins spot_finder_mask_0/s_axis_completion]
connect_bd_intf_net -intf_net axis_compl_fifo_7_M_AXIS [get_bd_intf_pins axis_compl_fifo_7/M_AXIS] [get_bd_intf_pins roi_calc_0/s_axis_completion]
connect_bd_intf_net -intf_net axis_data_fifo_0_M_AXIS [get_bd_intf_pins axis_data_fifo_0/M_AXIS] [get_bd_intf_pins pedestal_0/data_in]
connect_bd_intf_net -intf_net axis_data_fifo_10_M_AXIS [get_bd_intf_pins axis_data_fifo_10/M_AXIS] [get_bd_intf_pins stream_24bit_conv_0/data_in]
connect_bd_intf_net -intf_net axis_data_fifo_10_M_AXIS [get_bd_intf_pins axis_data_fifo_10/M_AXIS] [get_bd_intf_pins pixel_sqrt_0/data_in]
connect_bd_intf_net -intf_net axis_data_fifo_11_M_AXIS [get_bd_intf_pins axis_data_fifo_11/M_AXIS] [get_bd_intf_pins stream_24bit_conv_0/data_in]
connect_bd_intf_net -intf_net axis_data_fifo_1_M_AXIS [get_bd_intf_pins adu_histo_0/data_in] [get_bd_intf_pins axis_data_fifo_1/M_AXIS]
connect_bd_intf_net -intf_net axis_data_fifo_2_M_AXIS [get_bd_intf_pins axis_data_fifo_2/M_AXIS] [get_bd_intf_pins mask_missing_0/data_in]
connect_bd_intf_net -intf_net axis_data_fifo_3_M_AXIS [get_bd_intf_pins axis_data_fifo_3/M_AXIS] [get_bd_intf_pins eiger_reorder_0/data_in]
@@ -460,6 +470,7 @@ proc create_hier_cell_image_processing { parentCell nameHier } {
connect_bd_intf_net -intf_net pedestal_0_m_axi_d_hbm_p5 [get_bd_intf_pins pedestal_0/m_axi_d_hbm_p5] [get_bd_intf_pins smartconnect_5/S00_AXI]
connect_bd_intf_net -intf_net pedestal_0_m_axi_d_hbm_p5_w [get_bd_intf_pins pedestal_0/m_axi_d_hbm_p5_w] [get_bd_intf_pins smartconnect_5/S01_AXI]
connect_bd_intf_net -intf_net pedestal_0_m_axis_completion [get_bd_intf_pins axis_compl_fifo_0/S_AXIS] [get_bd_intf_pins pedestal_0/m_axis_completion]
connect_bd_intf_net -intf_net pixel_sqrt_0_data_out [get_bd_intf_pins axis_data_fifo_11/S_AXIS] [get_bd_intf_pins pixel_sqrt_0/data_out]
connect_bd_intf_net -intf_net roi_calc_0_data_out [get_bd_intf_pins axis_data_fifo_10/S_AXIS] [get_bd_intf_pins roi_calc_0/data_out]
connect_bd_intf_net -intf_net roi_calc_0_m_axis_completion [get_bd_intf_pins m_axis_completion] [get_bd_intf_pins roi_calc_0/m_axis_completion]
connect_bd_intf_net -intf_net roi_calc_0_roi_out [get_bd_intf_pins axis_roi_calc_result_fifo_0/S_AXIS] [get_bd_intf_pins roi_calc_0/roi_out]
@@ -483,10 +494,10 @@ proc create_hier_cell_image_processing { parentCell nameHier } {
connect_bd_intf_net -intf_net stream_24bit_conv_0_data_out [get_bd_intf_pins axis_register_slice_data_3/S_AXIS] [get_bd_intf_pins stream_24bit_conv_0/data_out]
# Create port connections
connect_bd_net -net ap_rst_n_1 [get_bd_pins ap_rst_n] [get_bd_pins adu_histo_0/ap_rst_n] [get_bd_pins axis_32_to_512_0/ap_rst_n] [get_bd_pins axis_64_to_512_0/ap_rst_n] [get_bd_pins eiger_reorder_0/ap_rst_n] [get_bd_pins frame_summation_0/ap_rst_n] [get_bd_pins integration_0/ap_rst_n] [get_bd_pins jf_conversion_0/ap_rst_n] [get_bd_pins mask_missing_0/ap_rst_n] [get_bd_pins pedestal_0/ap_rst_n] [get_bd_pins roi_calc_0/ap_rst_n] [get_bd_pins spot_finder_0/ap_rst_n] [get_bd_pins spot_finder_connecti_0/ap_rst_n] [get_bd_pins spot_finder_mask_0/ap_rst_n] [get_bd_pins spot_finder_merge_0/ap_rst_n] [get_bd_pins stream_24bit_conv_0/ap_rst_n]
connect_bd_net -net ap_rst_n_1 [get_bd_pins ap_rst_n] [get_bd_pins adu_histo_0/ap_rst_n] [get_bd_pins axis_32_to_512_0/ap_rst_n] [get_bd_pins axis_64_to_512_0/ap_rst_n] [get_bd_pins eiger_reorder_0/ap_rst_n] [get_bd_pins frame_summation_0/ap_rst_n] [get_bd_pins integration_0/ap_rst_n] [get_bd_pins jf_conversion_0/ap_rst_n] [get_bd_pins mask_missing_0/ap_rst_n] [get_bd_pins pedestal_0/ap_rst_n] [get_bd_pins pixel_sqrt_0/ap_rst_n] [get_bd_pins roi_calc_0/ap_rst_n] [get_bd_pins spot_finder_0/ap_rst_n] [get_bd_pins spot_finder_connecti_0/ap_rst_n] [get_bd_pins spot_finder_mask_0/ap_rst_n] [get_bd_pins spot_finder_merge_0/ap_rst_n] [get_bd_pins stream_24bit_conv_0/ap_rst_n]
connect_bd_net -net ap_start_1 [get_bd_pins frame_summation_0/ap_start] [get_bd_pins integration_0/ap_start] [get_bd_pins one/dout] [get_bd_pins spot_finder_0/ap_start] [get_bd_pins stream_24bit_conv_0/ap_start]
connect_bd_net -net axi_clk_1 [get_bd_pins axi_clk] [get_bd_pins adu_histo_0/ap_clk] [get_bd_pins axis_32_to_512_0/ap_clk] [get_bd_pins axis_64_to_512_0/ap_clk] [get_bd_pins axis_compl_fifo_0/s_axis_aclk] [get_bd_pins axis_compl_fifo_1/s_axis_aclk] [get_bd_pins axis_compl_fifo_2/s_axis_aclk] [get_bd_pins axis_compl_fifo_3/s_axis_aclk] [get_bd_pins axis_compl_fifo_4/s_axis_aclk] [get_bd_pins axis_compl_fifo_5/s_axis_aclk] [get_bd_pins axis_compl_fifo_6/s_axis_aclk] [get_bd_pins axis_compl_fifo_7/s_axis_aclk] [get_bd_pins axis_data_fifo_0/s_axis_aclk] [get_bd_pins axis_data_fifo_1/s_axis_aclk] [get_bd_pins axis_data_fifo_10/s_axis_aclk] [get_bd_pins axis_data_fifo_2/s_axis_aclk] [get_bd_pins axis_data_fifo_3/s_axis_aclk] [get_bd_pins axis_data_fifo_4/s_axis_aclk] [get_bd_pins axis_data_fifo_5/s_axis_aclk] [get_bd_pins axis_data_fifo_6/s_axis_aclk] [get_bd_pins axis_data_fifo_7/s_axis_aclk] [get_bd_pins axis_data_fifo_8/s_axis_aclk] [get_bd_pins axis_data_fifo_9/s_axis_aclk] [get_bd_pins axis_data_spot_finder_mask_0/s_axis_aclk] [get_bd_pins axis_integration_result_fifo_0/s_axis_aclk] [get_bd_pins axis_integration_result_fifo_1/s_axis_aclk] [get_bd_pins axis_register_slice_data_1/aclk] [get_bd_pins axis_register_slice_data_2/aclk] [get_bd_pins axis_register_slice_data_3/aclk] [get_bd_pins axis_roi_calc_result_fifo_0/s_axis_aclk] [get_bd_pins axis_spot_finder_conn_fifo_0/s_axis_aclk] [get_bd_pins axis_spot_finder_fifo_0/s_axis_aclk] [get_bd_pins axis_spot_finder_fifo_1/s_axis_aclk] [get_bd_pins axis_spot_finder_fifo_2/s_axis_aclk] [get_bd_pins axis_spot_finder_fifo_3/s_axis_aclk] [get_bd_pins eiger_reorder_0/ap_clk] [get_bd_pins frame_summation_0/ap_clk] [get_bd_pins integration_0/ap_clk] [get_bd_pins jf_conversion_0/ap_clk] [get_bd_pins mask_missing_0/ap_clk] [get_bd_pins pedestal_0/ap_clk] [get_bd_pins roi_calc_0/ap_clk] [get_bd_pins smartconnect_0/aclk] [get_bd_pins smartconnect_1/aclk] [get_bd_pins smartconnect_2/aclk] [get_bd_pins smartconnect_3/aclk] [get_bd_pins smartconnect_4/aclk] [get_bd_pins smartconnect_5/aclk] [get_bd_pins spot_finder_0/ap_clk] [get_bd_pins spot_finder_connecti_0/ap_clk] [get_bd_pins spot_finder_mask_0/ap_clk] [get_bd_pins spot_finder_merge_0/ap_clk] [get_bd_pins stream_24bit_conv_0/ap_clk]
connect_bd_net -net axi_rst_n_1 [get_bd_pins axi_rst_n] [get_bd_pins axis_compl_fifo_0/s_axis_aresetn] [get_bd_pins axis_compl_fifo_1/s_axis_aresetn] [get_bd_pins axis_compl_fifo_2/s_axis_aresetn] [get_bd_pins axis_compl_fifo_3/s_axis_aresetn] [get_bd_pins axis_compl_fifo_4/s_axis_aresetn] [get_bd_pins axis_compl_fifo_5/s_axis_aresetn] [get_bd_pins axis_compl_fifo_6/s_axis_aresetn] [get_bd_pins axis_compl_fifo_7/s_axis_aresetn] [get_bd_pins axis_data_fifo_0/s_axis_aresetn] [get_bd_pins axis_data_fifo_1/s_axis_aresetn] [get_bd_pins axis_data_fifo_10/s_axis_aresetn] [get_bd_pins axis_data_fifo_2/s_axis_aresetn] [get_bd_pins axis_data_fifo_3/s_axis_aresetn] [get_bd_pins axis_data_fifo_4/s_axis_aresetn] [get_bd_pins axis_data_fifo_5/s_axis_aresetn] [get_bd_pins axis_data_fifo_6/s_axis_aresetn] [get_bd_pins axis_data_fifo_7/s_axis_aresetn] [get_bd_pins axis_data_fifo_8/s_axis_aresetn] [get_bd_pins axis_data_fifo_9/s_axis_aresetn] [get_bd_pins axis_data_spot_finder_mask_0/s_axis_aresetn] [get_bd_pins axis_integration_result_fifo_0/s_axis_aresetn] [get_bd_pins axis_integration_result_fifo_1/s_axis_aresetn] [get_bd_pins axis_register_slice_data_1/aresetn] [get_bd_pins axis_register_slice_data_2/aresetn] [get_bd_pins axis_register_slice_data_3/aresetn] [get_bd_pins axis_roi_calc_result_fifo_0/s_axis_aresetn] [get_bd_pins axis_spot_finder_conn_fifo_0/s_axis_aresetn] [get_bd_pins axis_spot_finder_fifo_0/s_axis_aresetn] [get_bd_pins axis_spot_finder_fifo_1/s_axis_aresetn] [get_bd_pins axis_spot_finder_fifo_2/s_axis_aresetn] [get_bd_pins axis_spot_finder_fifo_3/s_axis_aresetn] [get_bd_pins smartconnect_0/aresetn] [get_bd_pins smartconnect_1/aresetn] [get_bd_pins smartconnect_2/aresetn] [get_bd_pins smartconnect_3/aresetn] [get_bd_pins smartconnect_4/aresetn] [get_bd_pins smartconnect_5/aresetn]
connect_bd_net -net axi_clk_1 [get_bd_pins axi_clk] [get_bd_pins adu_histo_0/ap_clk] [get_bd_pins axis_32_to_512_0/ap_clk] [get_bd_pins axis_64_to_512_0/ap_clk] [get_bd_pins axis_compl_fifo_0/s_axis_aclk] [get_bd_pins axis_compl_fifo_1/s_axis_aclk] [get_bd_pins axis_compl_fifo_2/s_axis_aclk] [get_bd_pins axis_compl_fifo_3/s_axis_aclk] [get_bd_pins axis_compl_fifo_4/s_axis_aclk] [get_bd_pins axis_compl_fifo_5/s_axis_aclk] [get_bd_pins axis_compl_fifo_6/s_axis_aclk] [get_bd_pins axis_compl_fifo_7/s_axis_aclk] [get_bd_pins axis_data_fifo_0/s_axis_aclk] [get_bd_pins axis_data_fifo_1/s_axis_aclk] [get_bd_pins axis_data_fifo_10/s_axis_aclk] [get_bd_pins axis_data_fifo_11/s_axis_aclk] [get_bd_pins axis_data_fifo_2/s_axis_aclk] [get_bd_pins axis_data_fifo_3/s_axis_aclk] [get_bd_pins axis_data_fifo_4/s_axis_aclk] [get_bd_pins axis_data_fifo_5/s_axis_aclk] [get_bd_pins axis_data_fifo_6/s_axis_aclk] [get_bd_pins axis_data_fifo_7/s_axis_aclk] [get_bd_pins axis_data_fifo_8/s_axis_aclk] [get_bd_pins axis_data_fifo_9/s_axis_aclk] [get_bd_pins axis_data_spot_finder_mask_0/s_axis_aclk] [get_bd_pins axis_integration_result_fifo_0/s_axis_aclk] [get_bd_pins axis_integration_result_fifo_1/s_axis_aclk] [get_bd_pins axis_register_slice_data_1/aclk] [get_bd_pins axis_register_slice_data_2/aclk] [get_bd_pins axis_register_slice_data_3/aclk] [get_bd_pins axis_roi_calc_result_fifo_0/s_axis_aclk] [get_bd_pins axis_spot_finder_conn_fifo_0/s_axis_aclk] [get_bd_pins axis_spot_finder_fifo_0/s_axis_aclk] [get_bd_pins axis_spot_finder_fifo_1/s_axis_aclk] [get_bd_pins axis_spot_finder_fifo_2/s_axis_aclk] [get_bd_pins axis_spot_finder_fifo_3/s_axis_aclk] [get_bd_pins eiger_reorder_0/ap_clk] [get_bd_pins frame_summation_0/ap_clk] [get_bd_pins integration_0/ap_clk] [get_bd_pins jf_conversion_0/ap_clk] [get_bd_pins mask_missing_0/ap_clk] [get_bd_pins pedestal_0/ap_clk] [get_bd_pins pixel_sqrt_0/ap_clk] [get_bd_pins roi_calc_0/ap_clk] [get_bd_pins smartconnect_0/aclk] [get_bd_pins smartconnect_1/aclk] [get_bd_pins smartconnect_2/aclk] [get_bd_pins smartconnect_3/aclk] [get_bd_pins smartconnect_4/aclk] [get_bd_pins smartconnect_5/aclk] [get_bd_pins spot_finder_0/ap_clk] [get_bd_pins spot_finder_connecti_0/ap_clk] [get_bd_pins spot_finder_mask_0/ap_clk] [get_bd_pins spot_finder_merge_0/ap_clk] [get_bd_pins stream_24bit_conv_0/ap_clk]
connect_bd_net -net axi_rst_n_1 [get_bd_pins axi_rst_n] [get_bd_pins axis_compl_fifo_0/s_axis_aresetn] [get_bd_pins axis_compl_fifo_1/s_axis_aresetn] [get_bd_pins axis_compl_fifo_2/s_axis_aresetn] [get_bd_pins axis_compl_fifo_3/s_axis_aresetn] [get_bd_pins axis_compl_fifo_4/s_axis_aresetn] [get_bd_pins axis_compl_fifo_5/s_axis_aresetn] [get_bd_pins axis_compl_fifo_6/s_axis_aresetn] [get_bd_pins axis_compl_fifo_7/s_axis_aresetn] [get_bd_pins axis_data_fifo_0/s_axis_aresetn] [get_bd_pins axis_data_fifo_1/s_axis_aresetn] [get_bd_pins axis_data_fifo_10/s_axis_aresetn] [get_bd_pins axis_data_fifo_11/s_axis_aresetn] [get_bd_pins axis_data_fifo_2/s_axis_aresetn] [get_bd_pins axis_data_fifo_3/s_axis_aresetn] [get_bd_pins axis_data_fifo_4/s_axis_aresetn] [get_bd_pins axis_data_fifo_5/s_axis_aresetn] [get_bd_pins axis_data_fifo_6/s_axis_aresetn] [get_bd_pins axis_data_fifo_7/s_axis_aresetn] [get_bd_pins axis_data_fifo_8/s_axis_aresetn] [get_bd_pins axis_data_fifo_9/s_axis_aresetn] [get_bd_pins axis_data_spot_finder_mask_0/s_axis_aresetn] [get_bd_pins axis_integration_result_fifo_0/s_axis_aresetn] [get_bd_pins axis_integration_result_fifo_1/s_axis_aresetn] [get_bd_pins axis_register_slice_data_1/aresetn] [get_bd_pins axis_register_slice_data_2/aresetn] [get_bd_pins axis_register_slice_data_3/aresetn] [get_bd_pins axis_roi_calc_result_fifo_0/s_axis_aresetn] [get_bd_pins axis_spot_finder_conn_fifo_0/s_axis_aresetn] [get_bd_pins axis_spot_finder_fifo_0/s_axis_aresetn] [get_bd_pins axis_spot_finder_fifo_1/s_axis_aresetn] [get_bd_pins axis_spot_finder_fifo_2/s_axis_aresetn] [get_bd_pins axis_spot_finder_fifo_3/s_axis_aresetn] [get_bd_pins smartconnect_0/aresetn] [get_bd_pins smartconnect_1/aresetn] [get_bd_pins smartconnect_2/aresetn] [get_bd_pins smartconnect_3/aresetn] [get_bd_pins smartconnect_4/aresetn] [get_bd_pins smartconnect_5/aresetn]
connect_bd_net -net axis_data_fifo_6_almost_empty [get_bd_pins proc_fifo_empty] [get_bd_pins axis_data_fifo_7/almost_empty]
connect_bd_net -net axis_data_fifo_6_almost_full [get_bd_pins proc_fifo_full] [get_bd_pins axis_data_fifo_7/almost_full]
connect_bd_net -net frame_summation_0_idle [get_bd_pins frame_summation_idle] [get_bd_pins frame_summation_0/idle]

View File

@@ -495,6 +495,7 @@ proc create_hier_cell_jungfraujoch { parentCell nameHier } {
connect_bd_net -net action_config_0_nmodules [get_bd_pins action_config_0/nmodules] [get_bd_pins data_collection_fsm_0/nmodules]
connect_bd_net -net action_config_0_nstorage_cells [get_bd_pins action_config_0/nstorage_cells] [get_bd_pins data_collection_fsm_0/nstorage_cells]
connect_bd_net -net action_config_0_nsummation [get_bd_pins action_config_0/nsummation] [get_bd_pins data_collection_fsm_0/nsummation]
connect_bd_net -net action_config_0_sqrtmult [get_bd_pins action_config_0/sqrtmult] [get_bd_pins data_collection_fsm_0/sqrtmult]
connect_bd_net -net action_config_0_spot_finder_count_threshold [get_bd_pins action_config_0/spot_finder_count_threshold] [get_bd_pins image_processing/in_count_threshold]
connect_bd_net -net action_config_0_spot_finder_d_max [get_bd_pins action_config_0/spot_finder_d_max] [get_bd_pins image_processing/in_max_d_value]
connect_bd_net -net action_config_0_spot_finder_d_min [get_bd_pins action_config_0/spot_finder_d_min] [get_bd_pins image_processing/in_min_d_value]

View File

@@ -92,7 +92,7 @@ if {$WNSPLACE > -0.3000} {
puts " ***** Final WNS: $WNSROUTE ps *****"
puts ""
if {$WNSROUTE >= -0.050} {
if {$WNSROUTE >= 0} {
write_bitstream -force -file ${bitstream_name} >> bitstream.log
if {$part eq {xcu55c-fsvh2892-2L-e}} {
write_cfgmem -force -size 128 -format mcs -interface SPIx4 -loadbit "up 0x01002000 ${bitstream_name}.bit" ${bitstream_name} >> cfgmem.log

View File

@@ -7,7 +7,9 @@ set_top $env(HLS_TOP_FUNCTION)
add_files $env(SRC_DIR)/$env(HLS_FILE)
if { [info exists ::env(HLS_TB_FILE)] } {
add_files -tb $env(SRC_DIR)/$env(HLS_TB_FILE)
if {$env(HLS_TB_FILE) != ""} {
add_files -tb $env(SRC_DIR)/$env(HLS_TB_FILE)
}
}
open_solution solution1
@@ -19,6 +21,12 @@ create_clock -period 3.2 -name default
config_interface -m_axi_addr64=true
config_schedule -enable_dsp_full_reg=true
if { [info exists ::env(HLS_TB_FILE)] } {
if {$env(HLS_TB_FILE) != ""} {
csim_design
}
}
csynth_design
config_export -vendor {psi.ch} -version 1.0 -ipname $env(HLS_TOP_FUNCTION) -format ip_catalog -rtl verilog

View File

@@ -659,7 +659,10 @@ namespace {
message.experiment_group = j["experiment_group"];
if (j.contains("jfjoch_release"))
message.jfjoch_release = j["jfjoch_release"];
if (j.contains("socket_number"))
message.socket_number = j["socket_number"];
if (j.contains("writer_notification_zmq_addr"))
message.writer_notification_zmq_addr = j["writer_notification_zmq_addr"];
} catch (const std::exception &e) {
throw JFJochException(JFJochExceptionCategory::CBORError,
"Cannot parse user_data as valid JSON " + std::string(e.what()));

View File

@@ -321,9 +321,13 @@ inline void CBOR_ENC_START_USER_DATA(CborEncoder& encoder, const char* key,
j["write_master_file"] = message.write_master_file.value();
if (message.data_reduction_factor_serialmx)
j["data_reduction_factor_serialmx"] = message.data_reduction_factor_serialmx.value();
if (message.experiment_group)
j["experiment_group"] = message.experiment_group.value();
j["experiment_group"] = message.experiment_group;
j["jfjoch_release"] = message.jfjoch_release;
if (message.socket_number)
j["socket_number"] = message.socket_number.value();
j["writer_notification_zmq_addr"] = message.writer_notification_zmq_addr;
auto str = j.dump();
CBOR_ENC(encoder, key, str);

View File

@@ -21,6 +21,7 @@ ADD_LIBRARY(ImagePusher STATIC
ImagePusher.cpp ImagePusher.h
TestImagePusher.cpp TestImagePusher.h
ZMQStream2Pusher.cpp ZMQStream2Pusher.h
ZMQWriterNotificationPuller.cpp ZMQWriterNotificationPuller.h
DumpCBORToFilePusher.cpp
DumpCBORToFilePusher.h)

View File

@@ -15,3 +15,9 @@ void PrepareCBORImage(DataMessage& message,
message.image.algorithm = experiment.GetCompressionAlgorithm();
message.image.channel = "default";
}
void ImagePusher::Finalize() {}
std::string ImagePusher::GetWriterNotificationSocketAddress() const {
return "socket1234";
}

View File

@@ -11,6 +11,7 @@
#include "CBORStream2Serializer.h"
#include "JFJochMessages.h"
#include "../common/ZeroCopyReturnValue.h"
#include "../common/Logger.h"
void PrepareCBORImage(DataMessage& message,
const DiffractionExperiment &experiment,
@@ -24,6 +25,9 @@ public:
virtual void SendImage(const uint8_t *image_data, size_t image_size, int64_t image_number,
ZeroCopyReturnValue *z) = 0;
virtual bool SendCalibration(const CompressedImage& message) = 0;
virtual void Finalize(); // Ensure that all streams are closed, can throw exception
virtual std::string GetWriterNotificationSocketAddress() const;
virtual ~ImagePusher() = default;
};

View File

@@ -142,6 +142,7 @@ struct StartMessage {
std::string detector_serial_number;
std::string run_name;
uint64_t run_number;
std::vector<std::string> gain_file_names;
std::vector<std::string> roi_names;
@@ -175,9 +176,12 @@ struct StartMessage {
nlohmann::json user_data;
std::optional<float> data_reduction_factor_serialmx;
std::optional<std::string> experiment_group;
std::string experiment_group;
std::string jfjoch_release;
std::optional<uint64_t> socket_number; // This is number of socket in ZeroMQ
std::string writer_notification_zmq_addr; // Socket to inform detector on writer done
};
struct EndMessage {

View File

@@ -13,58 +13,60 @@ There are minor differences at the moment:
## Start message
| Field name | Type | Description | Present in DECTRIS format |
|---------------------------|-----------------------------|-----------------------------------------------------------------------------------------------------------------------------------|:-------------------------:|
| type | String | value "start" | X |
| magic_number | uint64 | Number used to describe version of the Jungfraujoch data interface - to allow to detect inconsistency between sender and receiver | |
| detector_distance | float | Detector distance \[m\] | |
| detector_translation | float | Detector translation vector \[m\] | X |
| beam_center_x | float | Beam center in X direction \[pixels\] | X |
| beam_center_y | float | Beam center in Y direction \[pixels\] | X |
| number_of_images | uint64 | Number of images in the series | X |
| image_size_x | uint64 | Image width \[pixels\] | X |
| image_size_y | uint64 | Image height \[pixels\] | X |
| incident_energy | float | X-ray energy \[eV\] | X |
| incident_wavelength | float | X-ray wavelength \[Angstrom\] | X |
| frame_time | float | Frame time, if multiple frames per trigger \[s\] | X |
| count_time | float | Exposure time \[s\] | X |
| saturation_value | int64 | Maximum valid sample value | X |
| error_value | int64 | Value used in images to describe pixels that are in error state or missing | |
| pixel_size_x | float | Pixel width \[m\] | X |
| pixel_size_y | float | Pixel height \[m\] | X |
| sensor_thickness | float | Sensor thickness \[m\] | X |
| sensor_material | string | Sensor material | X |
| arm_data | data | Approximate date of arming | X |
| pixel_mask_enabled | bool | Pixel mask applied on images | X |
| detector_description | string | Name of the detector | X |
| series_unique_id | string | Unique text ID of the series (run_name parameter) | X |
| series_id | uint64 | Unique numeric ID of the series (run_number parameter) | X |
| goniometer | Map | See [DECTRIS documentation](https://github.com/dectris/documentation/tree/main/stream_v2) - only one axis is supported | X |
| pixel_mask | Map(string -> Image) | Pixel mask - multiple in case of storage cells | X |
| channels | Array(string) | List of image channels | X |
| max_spot_count | uint64 | Maximum number of spots identified in spot finding | |
| storage_cell_number | uint64 | Number of storage cells used by JUNGFRAU | |
| image_dtype | string | Pixel bit type (e.g. uint16) | X |
| unit_cell | Array(6 * float) (optional) | Unit cell of the system: a, b, c \[angstrom\] and alpha, beta, gamma \[degree\] | |
| az_int_bin_number | uint64 | Number of azimuthal integration bins | |
| az_int_bin_to_q | Array(float) | Q value for each azimuthal integration bin \[angstrom^-1\] | |
| summation | uint64 | Factor of frame summation | |
| user_data | string | JSON serialized to string that can contain the following fields: | X |
| - user | any valid JSON | Value of header_appendix provided at collection start to Jungfraujoch | |
| - source_name | string | Facility name | |
| - source_name_short | string | Facility name (short) | |
| - source_type | string (optional) | Type of X-ray source (use NXsource/type values, for example "Synchrotron X-ray Source" or "Free-Electron Laser") | |
| - instrument_name | string | Instrument name | |
| - instrument_name_short | string | Instrument name (short) | |
| - attenuator_transmission | float (optional) | Attenuator transmission \[\] | |
| - total_flux | float (optional) | Total flux \[ph/s\] | |
| - data_file_count | uint64 | Number of used data files | |
| - file_prefix | string | File prefix | |
| - sample_name | string | Name of the sample | |
| - rotation_axis | Array(float) | Rotation axis vector (array of size 3) | |
| - space_group_number | uint64 | Space group number | |
| - write_master_file | bool | With multiple sockets, it selects which socket will provide master file | |
| - experiment_group | string | ID of instrument user, e.g., p-group (SLS/SwissFEL) or proposal number | |
| Field name | Type | Description | Present in DECTRIS format |
|--------------------------------|-----------------------------|-----------------------------------------------------------------------------------------------------------------------------------|:-------------------------:|
| type | String | value "start" | X |
| magic_number | uint64 | Number used to describe version of the Jungfraujoch data interface - to allow to detect inconsistency between sender and receiver | |
| detector_distance | float | Detector distance \[m\] | |
| detector_translation | float | Detector translation vector \[m\] | X |
| beam_center_x | float | Beam center in X direction \[pixels\] | X |
| beam_center_y | float | Beam center in Y direction \[pixels\] | X |
| number_of_images | uint64 | Number of images in the series | X |
| image_size_x | uint64 | Image width \[pixels\] | X |
| image_size_y | uint64 | Image height \[pixels\] | X |
| incident_energy | float | X-ray energy \[eV\] | X |
| incident_wavelength | float | X-ray wavelength \[Angstrom\] | X |
| frame_time | float | Frame time, if multiple frames per trigger \[s\] | X |
| count_time | float | Exposure time \[s\] | X |
| saturation_value | int64 | Maximum valid sample value | X |
| error_value | int64 | Value used in images to describe pixels that are in error state or missing | |
| pixel_size_x | float | Pixel width \[m\] | X |
| pixel_size_y | float | Pixel height \[m\] | X |
| sensor_thickness | float | Sensor thickness \[m\] | X |
| sensor_material | string | Sensor material | X |
| arm_data | data | Approximate date of arming | X |
| pixel_mask_enabled | bool | Pixel mask applied on images | X |
| detector_description | string | Name of the detector | X |
| series_unique_id | string | Unique text ID of the series (run_name parameter) | X |
| series_id | uint64 | Unique numeric ID of the series (run_number parameter) | X |
| goniometer | Map | See [DECTRIS documentation](https://github.com/dectris/documentation/tree/main/stream_v2) - only one axis is supported | X |
| pixel_mask | Map(string -> Image) | Pixel mask - multiple in case of storage cells | X |
| channels | Array(string) | List of image channels | X |
| max_spot_count | uint64 | Maximum number of spots identified in spot finding | |
| storage_cell_number | uint64 | Number of storage cells used by JUNGFRAU | |
| image_dtype | string | Pixel bit type (e.g. uint16) | X |
| unit_cell | Array(6 * float) (optional) | Unit cell of the system: a, b, c \[angstrom\] and alpha, beta, gamma \[degree\] | |
| az_int_bin_number | uint64 | Number of azimuthal integration bins | |
| az_int_bin_to_q | Array(float) | Q value for each azimuthal integration bin \[angstrom^-1\] | |
| summation | uint64 | Factor of frame summation | |
| user_data | string | JSON serialized to string that can contain the following fields: | X |
| - user | any valid JSON | Value of header_appendix provided at collection start to Jungfraujoch | |
| - source_name | string | Facility name | |
| - source_name_short | string | Facility name (short) | |
| - source_type | string (optional) | Type of X-ray source (use NXsource/type values, for example "Synchrotron X-ray Source" or "Free-Electron Laser") | |
| - instrument_name | string | Instrument name | |
| - instrument_name_short | string | Instrument name (short) | |
| - attenuator_transmission | float (optional) | Attenuator transmission \[\] | |
| - total_flux | float (optional) | Total flux \[ph/s\] | |
| - data_file_count | uint64 | Number of used data files | |
| - file_prefix | string | File prefix | |
| - sample_name | string | Name of the sample | |
| - rotation_axis | Array(float) | Rotation axis vector (array of size 3) | |
| - space_group_number | uint64 | Space group number | |
| - write_master_file | bool | With multiple sockets, it selects which socket will provide master file | |
| - writer_notification_zmq_addr | string | ZeroMQ address to inform `jfjoch_broker` about writers that finished operation | |
| - socket_number | uint64 | Number of ZeroMQ socket (on `jfjoch_broker` side) used for transmission | |
| - experiment_group | string | ID of instrument user, e.g., p-group (SLS/SwissFEL) or proposal number | |
See [DECTRIS documentation](https://github.com/dectris/documentation/tree/main/stream_v2) for definition of Image as MultiDimArray with optional compression.

View File

@@ -55,17 +55,17 @@ void ZMQStream2Pusher::StartDataCollection(StartMessage& message) {
throw JFJochException(JFJochExceptionCategory::InputParameterInvalid,
"Images per file cannot be zero or negative");
images_per_file = message.images_per_file;
run_number = message.run_number;
run_name = message.run_name;
serializer.SerializeSequenceStart(message);
for (auto &s: socket) {
if (!s->Send(serialization_buffer.data(), serializer.GetBufferSize(), true))
throw JFJochException(JFJochExceptionCategory::ZeroMQ, "Timeout on pushing start message on addr "
+ s->GetEndpointName());
if (message.write_master_file) {
for (int i = 0; i < socket.size(); i++) {
message.socket_number = i;
if (i > 0)
message.write_master_file = false;
serializer.SerializeSequenceStart(message);
}
serializer.SerializeSequenceStart(message);
if (!socket[i]->Send(serialization_buffer.data(), serializer.GetBufferSize(), true))
throw JFJochException(JFJochExceptionCategory::ZeroMQ, "Timeout on pushing start message on addr "
+ socket[i]->GetEndpointName());
}
if (preview_socket)
@@ -115,3 +115,36 @@ std::string ZMQStream2Pusher::GetPreviewAddress() {
else
return "";
}
void ZMQStream2Pusher::Finalize() {
if (writer_notification_socket) {
for (int i = 0; i < socket.size(); i++) {
auto n = writer_notification_socket->Receive(run_number, run_name);
if (!n)
throw JFJochException(JFJochExceptionCategory::FileWriteError, "No notification received from writer");
else if (n->socket_number >= socket.size())
throw JFJochException(JFJochExceptionCategory::FileWriteError, "Wrong socket number provided in the message");
else if (!n->ok)
throw JFJochException(JFJochExceptionCategory::FileWriteError, "Writer (socket "
+ socket[n->socket_number]->GetEndpointName()
+ ") finished with error");
}
}
}
std::string ZMQStream2Pusher::GetWriterNotificationSocketAddress() const {
if (writer_notification_socket)
return writer_notification_socket->GetEndpointName();
else
return "";
}
ZMQStream2Pusher &ZMQStream2Pusher::WriterNotificationSocket(const std::string &addr) {
writer_notification_socket = std::make_unique<ZMQWriterNotificationPuller>(addr);
return *this;
}
ZMQStream2Pusher &ZMQStream2Pusher::PreviewCounterPeriod(std::chrono::microseconds input) {
preview_counter.Period(input);
return *this;
}

Some files were not shown because too many files have changed in this diff Show More