Merge branch 'dev231218' into 'main'

Modifications in preparation to MAX IV experiment

See merge request jungfraujoch/nextgendcu!21
This commit is contained in:
2024-01-27 21:23:57 +01:00
250 changed files with 9363 additions and 3022 deletions
+21 -4
View File
@@ -20,6 +20,23 @@ build:x86:gcc:
- cmake -DCMAKE_BUILD_TYPE=Release ..
- make -j48 jfjoch
build:x86:gcc_writer:
stage: build
variables:
GIT_SUBMODULE_STRATEGY: recursive
CC: gcc
CXX: g++
tags:
- gcc
- x86
needs: []
script:
- mkdir build
- cd build
- source /opt/rh/gcc-toolset-12/enable
- cmake -DCMAKE_BUILD_TYPE=Release -DJFJOCH_WRITER_ONLY=ON ..
- make -j48 jfjoch
build:x86:driver:
stage: build
variables:
@@ -49,7 +66,7 @@ build:x86:vitis_hls:
- fpga/scripts/*
- fpga/xdc/*
- fpga/microblaze/*
- common/Definitions.h
- fpga/include/jfjoch_fpga.h
script:
- source /opt/Xilinx/Vitis_HLS/2022.1/settings64.sh
- mkdir build
@@ -69,10 +86,10 @@ build:x86:frontend:
- npm install
- npm run build
- cd build
- zip ../../frontend.zip *
- zip -r ../../frontend.${CI_COMMIT_SHORT_SHA}.zip *
artifacts:
paths:
- frontend.zip
- frontend.${CI_COMMIT_SHORT_SHA}.zip
expire_in: 1 week
test:x86:gcc:
@@ -193,7 +210,7 @@ synthesis:vivado_pcie_100g:
- fpga/hdl/*
- fpga/scripts/*
- fpga/xdc/*
- common/Definitions.h
- fpga/include/jfjoch_fpga.h
tags:
- vivado
artifacts:
+6 -4
View File
@@ -1,4 +1,4 @@
CMAKE_MINIMUM_REQUIRED(VERSION 3.18)
CMAKE_MINIMUM_REQUIRED(VERSION 3.19)
PROJECT(Jungfraujoch VERSION 1.0 LANGUAGES C CXX)
@@ -40,12 +40,13 @@ ADD_SUBDIRECTORY(common)
ADD_SUBDIRECTORY(writer)
ADD_SUBDIRECTORY(frame_serialize)
ADD_SUBDIRECTORY(broker/pistache)
IF (JFJOCH_WRITER_ONLY)
MESSAGE(STATUS "Compiling HDF5 writer only")
SET(jfjoch_executables jfjoch_writer)
SET(jfjoch_executables jfjoch_writer jfjoch_writer_http)
ELSE()
ADD_SUBDIRECTORY(broker)
ADD_SUBDIRECTORY(etc)
ADD_SUBDIRECTORY(fpga)
ADD_SUBDIRECTORY(acquisition_device)
ADD_SUBDIRECTORY(receiver)
@@ -53,7 +54,8 @@ ELSE()
ADD_SUBDIRECTORY(detector_control)
ADD_SUBDIRECTORY(tests)
ADD_SUBDIRECTORY(tools)
SET(jfjoch_executables jfjoch_broker jfjoch_writer CatchTest CompressionBenchmark HDF5DatasetWriteTest jfjoch_udp_simulator sls_detector_put sls_detector_get)
# ADD_SUBDIRECTORY(export_images)
SET(jfjoch_executables jfjoch_broker jfjoch_writer jfjoch_writer_http CatchTest CompressionBenchmark HDF5DatasetWriteTest jfjoch_udp_simulator sls_detector_put sls_detector_get)
ENDIF()
ADD_CUSTOM_COMMAND(OUTPUT frontend_ui/build/index.html
+2
View File
@@ -32,6 +32,8 @@ Required:
* HDF5 library version 1.10 or newer
* ZeroMQ library
* OpenSSL library
* TIFF library + C++ binding (optional)
* JPEG library (optional)
Optional:
* CUDA compiler version 11 or newer - image analysis features won't work without it
+2 -1
View File
@@ -54,7 +54,8 @@ void AcquisitionCounters::UpdateCounters(const Completion *c) {
if (c->module_number >= nmodules)
throw JFJochException(JFJochExceptionCategory::InputParameterInvalid,
"UpdateCounters wrong module number: " + std::to_string(c->module_number) + " for frame " + std::to_string(c->frame_number));
"UpdateCounters wrong module number: " + std::to_string(c->module_number) + " for frame " + std::to_string(c->frame_number) +
" and handle " + std::to_string(c->handle));
if (c->frame_number >= expected_frames)
throw JFJochException(JFJochExceptionCategory::InputParameterInvalid,
"UpdateCounters frame number is out of bounds");
+44 -21
View File
@@ -32,8 +32,7 @@ void *mmap_acquisition_buffer(size_t size, int16_t numa_node) {
return ret;
}
AcquisitionDevice::AcquisitionDevice(uint16_t in_data_stream) :
buffer_err(FPGA_BUFFER_LOCATION_SIZE) {
AcquisitionDevice::AcquisitionDevice(uint16_t in_data_stream) {
logger = nullptr;
data_stream = in_data_stream;
}
@@ -53,13 +52,6 @@ void AcquisitionDevice::StartAction(const DiffractionExperiment &experiment, uin
throw(JFJochException(JFJochExceptionCategory::InputParameterAboveMax,
"Number of modules exceeds max possible for FPGA"));
for (int i = 0; i < RAW_MODULE_SIZE; i++) {
if (experiment.GetDetectorMode() == DetectorMode::Conversion)
buffer_err[i] = PIXEL_OUT_LOST;
else
buffer_err[i] = -1;
}
counters.Reset(experiment, data_stream);
expected_frames = experiment.GetFrameNum() / experiment.GetSummation();
@@ -78,13 +70,25 @@ void AcquisitionDevice::StartAction(const DiffractionExperiment &experiment, uin
StartSendingWorkRequests();
start_time = std::chrono::system_clock::now();
if (experiment.IsUsingInternalPacketGen())
RunInternalGenerator(experiment);
}
void AcquisitionDevice::WaitForActionComplete(bool pedestal_mode) {
auto c = work_completion_queue.GetBlocking();
while (c.type != Completion::Type::End) {
auto output = GetDeviceOutput(c.handle);
DeviceOutput* output;
try {
output = GetDeviceOutput(c.handle);
} catch (const JFJochException &e) {
if (logger)
logger->ErrorException(e);
continue;
}
c.module_number = output->module_statistics.module_number;
c.packet_count = output->module_statistics.packet_count;
c.frame_number = output->module_statistics.frame_number;
@@ -101,11 +105,22 @@ void AcquisitionDevice::WaitForActionComplete(bool pedestal_mode) {
data_stream, c.frame_number, c.module_number, c.handle);
SendWorkRequest(c.handle);
} else if (pedestal_mode && !c.pedestal) {
try {
counters.UpdateCounters(&c);
} catch (const JFJochException &e) {
if (logger)
logger->ErrorException(e);
}
SendWorkRequest(c.handle);
} else
counters.UpdateCounters(&c);
} else {
try {
counters.UpdateCounters(&c);
} catch (const JFJochException &e) {
if (logger)
logger->ErrorException(e);
SendWorkRequest(c.handle);
}
}
if (logger != nullptr)
logger->Debug("Data stream {} completion frame number {} module {} handle {}",
data_stream, c.frame_number, c.module_number, c.handle);
@@ -134,7 +149,7 @@ const DeviceOutput *AcquisitionDevice::GetDeviceOutput(size_t frame_number, uint
if (handle != HandleNotValid)
return GetDeviceOutput(handle);
else
return (DeviceOutput *) GetErrorFrameBuffer();
throw JFJochException(JFJochExceptionCategory::ArrayOutOfBounds, "Frame not collected");
}
const DeviceOutput *AcquisitionDevice::GetDeviceOutputPedestal(size_t storage_cell, uint16_t module_number) const {
@@ -142,11 +157,7 @@ const DeviceOutput *AcquisitionDevice::GetDeviceOutputPedestal(size_t storage_ce
if (handle != HandleNotValid)
return GetDeviceOutput(handle);
else
return (DeviceOutput *) GetErrorFrameBuffer();
}
const int16_t *AcquisitionDevice::GetErrorFrameBuffer() const {
return buffer_err.data();
throw JFJochException(JFJochExceptionCategory::ArrayOutOfBounds, "Frame not collected");
}
const DeviceOutput *AcquisitionDevice::GetDeviceOutput(size_t handle) const {
@@ -172,9 +183,9 @@ void AcquisitionDevice::InitializeIntegrationMap(const DiffractionExperiment &ex
const std::vector<uint16_t> &v,
const std::vector<float> &weights) {}
void AcquisitionDevice::MapBuffersStandard(size_t c2h_buffer_count, size_t h2c_buffer_count, int16_t numa_node) {
void AcquisitionDevice::MapBuffersStandard(size_t c2h_buffer_count, int16_t numa_node) {
try {
for (int i = 0; i < std::max(c2h_buffer_count, h2c_buffer_count); i++)
for (int i = 0; i < c2h_buffer_count; i++)
buffer_device.emplace_back((DeviceOutput *) mmap_acquisition_buffer(FPGA_BUFFER_LOCATION_SIZE, numa_node));
} catch (const JFJochException &e) {
UnmapBuffers();
@@ -267,3 +278,15 @@ void AcquisitionDevice::SetDefaultDataSource(AcquisitionDeviceSource id) {
AcquisitionDeviceSource AcquisitionDevice::GetDataSource() {
return AcquisitionDeviceSource::NONE;
}
void AcquisitionDevice::RunInternalGenerator(const DiffractionExperiment &experiment) {
FrameGeneratorConfig config{};
config.frames = experiment.GetFrameNum() + DELAY_FRAMES_STOP_AND_QUIT + 1;
config.modules = experiment.GetModulesNum(data_stream);
config.bunchid = INT_PKT_GEN_BUNCHID;
config.exptime = INT_PKT_GEN_EXPTTIME;
config.debug = INT_PKT_GEN_DEBUG;
config.dest_mac_addr = MacAddressFromStr(GetMACAddress());
config.dest_ipv4_addr = IPv4AddressFromStr(GetIPv4Address());
HW_RunInternalGenerator(config);
}
+6 -9
View File
@@ -14,11 +14,11 @@
#include "../common/ThreadSafeFIFO.h"
#include "../jungfrau/JFCalibration.h"
#include "../fpga/pcie_driver/ActionConfig.h"
#include "AcquisitionCounters.h"
#include "Completion.h"
#include "../fpga/host_library/DeviceOutput.h"
#include "../fpga/include/jfjoch_fpga.h"
#include "../common/NetworkAddressConvert.h"
struct AcquisitionDeviceStatistics {
uint64_t good_packets;
@@ -34,8 +34,6 @@ struct AcquisitionDeviceStatistics {
enum class AcquisitionDeviceSource {MAC_100G, MAC_4x10G, FRAME_GENERATOR, NONE};
class AcquisitionDevice {
std::vector<int16_t> buffer_err;
std::chrono::time_point<std::chrono::system_clock> start_time;
std::chrono::time_point<std::chrono::system_clock> end_time;
@@ -58,13 +56,13 @@ protected:
uint32_t max_modules = 1;
uint64_t mac_addr;
uint32_t ipv4_addr;
std::atomic<uint32_t> work_completion_count;
explicit AcquisitionDevice(uint16_t data_stream);
void UnmapBuffers();
void MapBuffersStandard(size_t c2h_buffer_count, size_t h2c_buffer_count, int16_t numa_node);
void MapBuffersStandard(size_t c2h_buffer_count, int16_t numa_node);
const DeviceOutput *GetDeviceOutput(size_t handle) const;
DeviceOutput *GetDeviceOutput(size_t handle);
virtual void HW_RunInternalGenerator(const FrameGeneratorConfig& config) = 0;
public:
AcquisitionDevice(const AcquisitionDevice &other) = delete;
AcquisitionDevice &operator=(const AcquisitionDevice &other) = delete;
@@ -89,9 +87,7 @@ public:
AcquisitionDeviceStatistics GetStatistics() const;
const DeviceOutput *GetDeviceOutput(size_t frame_number, uint16_t module_number) const;
const DeviceOutput *GetDeviceOutputPedestal(size_t frame_number, uint16_t module_number) const;
void FrameBufferRelease(size_t frame_number, uint16_t module_number);
const int16_t *GetErrorFrameBuffer() const;
// Calibration
virtual void InitializeCalibration(const DiffractionExperiment &experiment, const JFCalibration &calib);
@@ -100,7 +96,7 @@ public:
const std::vector<float> &weights);
const AcquisitionCounters& Counters() const;
virtual void SetSpotFinderParameters(int16_t count_threshold, double snr_threshold) {};
virtual void SetSpotFinderParameters(int32_t count_threshold, float snr_threshold) {};
virtual std::string GetIPv4Address() const;
virtual void SetIPv4Address(uint32_t ipv4_addr_network_order);
virtual void SetMACAddress(uint64_t mac_addr_network_order);
@@ -116,6 +112,7 @@ public:
AcquisitionDeviceNetConfig GetNetConfig() const;
virtual uint32_t GetExpectedDescriptorsPerModule() const = 0;
void RunInternalGenerator(const DiffractionExperiment& experiment);
};
@@ -33,4 +33,14 @@ std::vector<AcquisitionDeviceNetConfig> AcquisitionDeviceGroup::GetNetworkConfig
for (const auto &i: aq_devices)
ret.push_back(i->GetNetConfig());
return ret;
}
void AcquisitionDeviceGroup::SetDefaultDataSource(AcquisitionDeviceSource id) {
for (auto &i: aq_devices)
i->SetDefaultDataSource(id);
}
void AcquisitionDeviceGroup::EnableLogging(Logger *logger) {
for (auto &i: aq_devices)
i->EnableLogging(logger);
}
+2 -1
View File
@@ -15,8 +15,9 @@ public:
void Add(std::unique_ptr<AcquisitionDevice> &&device);
void AddPCIeDevice(const std::string &device_name);
void AddHLSDevice(int64_t buffer_size_modules);
void AddMockDevice(int64_t buffer_size_modules);
std::vector<AcquisitionDeviceNetConfig> GetNetworkConfig();
void SetDefaultDataSource(AcquisitionDeviceSource id);
void EnableLogging(Logger *logger);
};
#endif //JUNGFRAUJOCH_ACQUISITIONDEVICEGROUP_H
+1 -1
View File
@@ -2,7 +2,7 @@ ADD_LIBRARY(JungfraujochAcqusitionDevice STATIC
AcquisitionDevice.cpp AcquisitionDevice.h
AcquisitionCounters.cpp AcquisitionCounters.h
HLSSimulatedDevice.cpp HLSSimulatedDevice.h
Completion.cpp Completion.h ../fpga/pcie_driver/ActionConfig.h
Completion.cpp Completion.h ../fpga/include/jfjoch_fpga.h
PCIExpressDevice.cpp PCIExpressDevice.h
FPGAAcquisitionDevice.cpp FPGAAcquisitionDevice.h
AcquisitionDeviceGroup.cpp
+138 -81
View File
@@ -1,9 +1,7 @@
// Copyright (2019-2023) Paul Scherrer Institute
#include "FPGAAcquisitionDevice.h"
#include <random>
#include <bitset>
#include "../common/to_fixed.h"
#include "FPGAAcquisitionDevice.h"
void FPGAAcquisitionDevice::StartSendingWorkRequests() {
stop_work_requests = false;
@@ -27,26 +25,47 @@ void FPGAAcquisitionDevice::Finalize() {
void FPGAAcquisitionDevice::ReadWorkCompletionThread() {
uint32_t values;
if (logger)
logger->Debug("Starting read work completion thread for stream {}", data_stream);
Completion c{};
bool quit_loop = false;
do {
while (!HW_ReadMailbox(&values))
std::this_thread::sleep_for(std::chrono::microseconds(10));
c = parse_hw_completion(values);
if (c.data_collection_id == data_collection_id) {
work_completion_queue.PutBlocking(c);
if (c.type == Completion::Type::End)
quit_loop = true;
} else if (logger) {
if (c.type == Completion::Type::Start)
logger->Warning("Stream {} Start completion with wrong data collection ID", data_stream);
else
logger->Warning("Stream {} Image completion with wrong data collection ID frame {} module {}",
data_stream, c.frame_number, c.module_number);
bool read;
try {
read = HW_ReadMailbox(&values);
} catch (const JFJochException& e) {
if (logger)
logger->ErrorException(e);
read = false;
}
if (read) {
c = parse_hw_completion(values);
if (logger) {
logger->Debug("Stream {} Completion data collection ID {} type {} frame {} module {}",
data_stream,
c.data_collection_id,
(int)c.type,
c.frame_number,
c.module_number);
}
if (c.data_collection_id == data_collection_id) {
work_completion_queue.PutBlocking(c);
if (c.type == Completion::Type::End)
quit_loop = true;
} else if (logger) {
if (c.type == Completion::Type::Start)
logger->Warning("Stream {} Start completion with wrong data collection ID", data_stream);
else
logger->Warning("Stream {} Image completion with wrong data collection ID frame {} module {}",
data_stream, c.frame_number, c.module_number);
}
} else
std::this_thread::sleep_for(std::chrono::microseconds(10));
} while (!quit_loop);
if (logger)
logger->Debug("Done read work completion thread for stream {}", data_stream);
}
void FPGAAcquisitionDevice::SendWorkRequestThread() {
@@ -73,6 +92,7 @@ void FPGAAcquisitionDevice::InitializeIntegrationMap(const DiffractionExperiment
const std::vector<uint16_t> &v,
const std::vector<float> &weights) {
auto offset = experiment.GetFirstModuleOfDataStream(data_stream);
size_t modules = experiment.GetModulesNum(data_stream);
if (v.size() != experiment.GetModulesNum() * RAW_MODULE_SIZE)
throw JFJochException(JFJochExceptionCategory::InputParameterInvalid,
@@ -82,22 +102,21 @@ void FPGAAcquisitionDevice::InitializeIntegrationMap(const DiffractionExperiment
throw JFJochException(JFJochExceptionCategory::InputParameterInvalid,
"Mismatch regarding weights array");
size_t modules = experiment.GetModulesNum(data_stream);
if (modules > 2 * buffer_device.size())
throw JFJochException(JFJochExceptionCategory::InputParameterInvalid,
"Not enough host/FPGA buffers to load all integration map values");
for (int m = 0; m < modules; m++)
memcpy(buffer_device[m], v.data() + (offset + m) * RAW_MODULE_SIZE, RAW_MODULE_SIZE * sizeof(uint16_t));
for (int m = 0; m < modules; m++) {
for (int i = 0; i < RAW_MODULE_SIZE; i++) {
buffer_device[modules + m]->pixels[i] = to_fixed(weights[(offset + m) * RAW_MODULE_SIZE + i], 15);
}
for (uint32_t m = 0; m < modules; m++) {
memcpy(buffer_device[0]->pixels, v.data() + (offset + m) * RAW_MODULE_SIZE, RAW_MODULE_SIZE * sizeof(uint16_t));
buffer_device[0]->module_statistics.module_number = m;
buffer_device[0]->module_statistics.load_calibration_destination = LOAD_CALIBRATION_DEST_INTEGRATION_MAP;
LoadCalibration(0);
}
for (uint32_t m = 0; m < modules; m++) {
for (int i = 0; i < RAW_MODULE_SIZE; i++)
((float *)buffer_device[0]->pixels)[i] = weights[(offset + m) * RAW_MODULE_SIZE + i];
buffer_device[0]->module_statistics.module_number = m;
buffer_device[0]->module_statistics.load_calibration_destination = LOAD_CALIBRATION_DEST_INTEGRATION_WEIGHTS;
LoadCalibration(0);
}
HW_LoadIntegrationMap(modules);
}
void FPGAAcquisitionDevice::SetInternalGeneratorFrameForAllModules(const std::vector<uint16_t> &v) {
@@ -111,14 +130,13 @@ void FPGAAcquisitionDevice::SetInternalGeneratorFrameForAllModules(const std::ve
v.data(), RAW_MODULE_SIZE * sizeof(uint16_t));
}
if (max_modules > buffer_device.size())
throw JFJochException(JFJochExceptionCategory::InputParameterInvalid,
"Not enough host/FPGA buffers to load all integration map values");
memcpy(buffer_device[0]->pixels, internal_pkt_gen_frame.data(), RAW_MODULE_SIZE * sizeof(uint16_t));
for (int m = 0; m < max_modules; m++)
memcpy(buffer_device[m], internal_pkt_gen_frame.data() + m * RAW_MODULE_SIZE, RAW_MODULE_SIZE * sizeof(uint16_t));
HW_LoadInternalGeneratorFrame(max_modules);
buffer_device[0]->module_statistics.load_calibration_destination = LOAD_CALIBRATION_DEST_FRAME_GEN;
for (uint32_t m = 0; m < max_modules; m++) {
buffer_device[0]->module_statistics.module_number = m;
LoadCalibration(0);
}
}
@@ -140,10 +158,13 @@ void FPGAAcquisitionDevice::SetInternalGeneratorFrame(const std::vector<uint16_t
throw JFJochException(JFJochExceptionCategory::InputParameterInvalid,
"Not enough host/FPGA buffers to load all integration map values");
for (int m = 0; m < nmodules; m++)
memcpy(buffer_device[m], internal_pkt_gen_frame.data() + m * RAW_MODULE_SIZE, RAW_MODULE_SIZE * sizeof(uint16_t));
HW_LoadInternalGeneratorFrame(nmodules);
for (uint32_t m = 0; m < nmodules; m++) {
memcpy(buffer_device[0], internal_pkt_gen_frame.data() + m * RAW_MODULE_SIZE,
RAW_MODULE_SIZE * sizeof(uint16_t));
buffer_device[0]->module_statistics.module_number = m;
buffer_device[0]->module_statistics.load_calibration_destination = LOAD_CALIBRATION_DEST_FRAME_GEN;
LoadCalibration(0);
}
}
void FPGAAcquisitionDevice::InitializeCalibration(const DiffractionExperiment &experiment, const JFCalibration &calib) {
@@ -160,58 +181,87 @@ void FPGAAcquisitionDevice::InitializeCalibration(const DiffractionExperiment &e
size_t modules = experiment.GetModulesNum(data_stream);
size_t storage_cells = experiment.GetStorageCellNumber();
if (modules * (3 + 3 * storage_cells) > buffer_device.size())
throw JFJochException(JFJochExceptionCategory::InputParameterInvalid,
"Not enough host/FPGA buffers to load all calibration constants");
for (uint32_t m = 0; m < modules; m++) {
if (experiment.IsFixedGainG1()) {
calib.GainCalibration(m).ExportFixedG1(buffer_device[0]);
buffer_device[0]->module_statistics.module_number = m;
buffer_device[0]->module_statistics.load_calibration_destination = LOAD_CALIBRATION_DEST_GAIN_G1;
LoadCalibration(0);
} else {
if (experiment.IsUsingGainHG0())
calib.GainCalibration(m).ExportHG0(buffer_device[0]);
else
calib.GainCalibration(m).ExportG0(buffer_device[0]);
buffer_device[0]->module_statistics.module_number = m;
buffer_device[0]->module_statistics.load_calibration_destination = LOAD_CALIBRATION_DEST_GAIN_G0;
LoadCalibration(0);
for (int m = 0; m < modules; m++) {
calib.GainCalibration(m).ExportG0((uint16_t *) buffer_device[m]->pixels);
calib.GainCalibration(m).ExportG1((uint16_t *) buffer_device[m + modules]->pixels);
calib.GainCalibration(m).ExportG2((uint16_t *) buffer_device[m + modules * 2]->pixels);
calib.GainCalibration(m).ExportG1(buffer_device[0]);
buffer_device[0]->module_statistics.module_number = m;
buffer_device[0]->module_statistics.load_calibration_destination = LOAD_CALIBRATION_DEST_GAIN_G1;
LoadCalibration(0);
calib.GainCalibration(m).ExportG2(buffer_device[0]);
buffer_device[0]->module_statistics.module_number = m;
buffer_device[0]->module_statistics.load_calibration_destination = LOAD_CALIBRATION_DEST_GAIN_G2;
LoadCalibration(0);
}
}
for (int s = 0; s < storage_cells; s++) {
auto mask = calib.CalculateMask(experiment, s);
for (int m = 0; m < modules; m++) {
auto pedestal_g0 = calib.Pedestal(offset + m, 0, s).GetPedestal();
auto pedestal_g1 = calib.Pedestal(offset + m, 1, s).GetPedestal();
auto pedestal_g2 = calib.Pedestal(offset + m, 2, s).GetPedestal();
for (int i = 0; i < RAW_MODULE_SIZE; i++) {
if (experiment.GetApplyPixelMaskInFPGA() && (mask[(offset + m) * RAW_MODULE_SIZE + i] != 0)) {
buffer_device[(3 + 0 * storage_cells + s) * modules + m]->pixels[i] = 16384;
buffer_device[(3 + 1 * storage_cells + s) * modules + m]->pixels[i] = 16384;
buffer_device[(3 + 2 * storage_cells + s) * modules + m]->pixels[i] = 16384;
} else {
((uint16_t *) buffer_device[(3 + 0 * storage_cells + s) * modules + m]->pixels)[i] = pedestal_g0[i];
((uint16_t *) buffer_device[(3 + 1 * storage_cells + s) * modules + m]->pixels)[i] = pedestal_g1[i];
((uint16_t *) buffer_device[(3 + 2 * storage_cells + s) * modules + m]->pixels)[i] = pedestal_g2[i];
}
}
auto pedestal_g1 = calib.Pedestal(offset + m, 1, s).GetPedestal();
for (int i = 0; i < RAW_MODULE_SIZE; i++) {
if (experiment.GetApplyPixelMaskInFPGA() && (mask[(offset + m) * RAW_MODULE_SIZE + i] != 0))
buffer_device[0]->pixels[i] = 16384;
else
((uint16_t *) buffer_device[0]->pixels)[i] = pedestal_g1[i];
}
buffer_device[0]->module_statistics.module_number = m + modules * s;
buffer_device[0]->module_statistics.load_calibration_destination = LOAD_CALIBRATION_DEST_PEDESTAL_G1;
LoadCalibration(0);
if (!experiment.IsFixedGainG1()) {
auto pedestal_g0 = calib.Pedestal(offset + m, 0, s).GetPedestal();
for (int i = 0; i < RAW_MODULE_SIZE; i++) {
if (experiment.GetApplyPixelMaskInFPGA() && (mask[(offset + m) * RAW_MODULE_SIZE + i] != 0))
buffer_device[0]->pixels[i] = 16384;
else
((uint16_t *) buffer_device[0]->pixels)[i] = pedestal_g0[i];
}
buffer_device[0]->module_statistics.module_number = m + modules * s;
buffer_device[0]->module_statistics.load_calibration_destination = LOAD_CALIBRATION_DEST_PEDESTAL_G0;
LoadCalibration(0);
auto pedestal_g2 = calib.Pedestal(offset + m, 2, s).GetPedestal();
for (int i = 0; i < RAW_MODULE_SIZE; i++) {
if (experiment.GetApplyPixelMaskInFPGA() && (mask[(offset + m) * RAW_MODULE_SIZE + i] != 0))
buffer_device[0]->pixels[i] = 16384;
else
((uint16_t *) buffer_device[0]->pixels)[i] = pedestal_g2[i];
}
buffer_device[0]->module_statistics.module_number = m + modules * s;
buffer_device[0]->module_statistics.load_calibration_destination = LOAD_CALIBRATION_DEST_PEDESTAL_G2;
LoadCalibration(0);
}
}
}
HW_LoadCalibration(modules, storage_cells);
}
union float_uint32 {
float f;
uint32_t u;
};
inline uint32_t float2uint(float f) {
float_uint32 fu;
fu.f = f;
return fu.u;
}
void FPGAAcquisitionDevice::FillActionRegister(const DiffractionExperiment& x, DataCollectionConfig &job) {
std::random_device rd;
std::uniform_int_distribution<uint16_t> dist;
// Avoid data_collection_id of DATA_COLLECTION_ID_PURGE - this is reserved for cleaning unused work requests from the FPGA
data_collection_id = dist(rd);
while (data_collection_id == DATA_COLLECTION_ID_PURGE)
data_collection_id = dist(rd);
job.nmodules = x.GetModulesNum(data_stream) - 1;
job.nframes = x.GetFrameNum();
job.one_over_energy = float2uint(1 / x.GetPhotonEnergy_keV());
job.energy_kev = x.GetPhotonEnergy_keV();
job.nstorage_cells = x.GetStorageCellNumber() - 1;
job.mode = data_collection_id << 16;
job.nsummation = x.GetSummation() - 1;
@@ -235,6 +285,9 @@ void FPGAAcquisitionDevice::FillActionRegister(const DiffractionExperiment& x, D
break;
}
if (x.IsFixedGainG1())
job.mode |= MODE_FIXG1;
if (!x.IsPixelSigned())
job.mode |= MODE_UNSIGNED;
if (x.GetPixelDepth() == 4)
@@ -290,17 +343,17 @@ FPGAAcquisitionDevice::FPGAAcquisitionDevice(uint16_t data_stream)
internal_pkt_gen_frame(RAW_MODULE_SIZE * MAX_MODULES_FPGA) {
}
void FPGAAcquisitionDevice::SetSpotFinderParameters(int16_t count_threshold, double snr_threshold) {
void FPGAAcquisitionDevice::SetSpotFinderParameters(int32_t count_threshold, float snr_threshold) {
if (snr_threshold < 0) {
if (logger)
logger->Warning("Trying to set SNR threshold below zero: {}", snr_threshold );
snr_threshold = 0;
} else if (snr_threshold > 64) {
} else if (snr_threshold > 16) {
if (logger)
logger->Warning("Trying to set SNR threshold too high: {}", snr_threshold );
snr_threshold = 64;
snr_threshold = 16;
}
SpotFinderParameters params{.count_threshold = count_threshold, .snr_threshold = to_fixed(snr_threshold, 2)};
SpotFinderParameters params{.count_threshold = count_threshold, .snr_threshold = snr_threshold};
HW_SetSpotFinderParameters(params);
}
@@ -342,3 +395,7 @@ void FPGAAcquisitionDevice::SetDataSource(AcquisitionDeviceSource id) {
uint32_t FPGAAcquisitionDevice::GetExpectedDescriptorsPerModule() const {
return expected_descriptors_per_module;
}
void FPGAAcquisitionDevice::LoadCalibration(uint32_t handle) {
HW_LoadCalibration(LoadCalibrationConfig{.handle = handle});
}
+4 -5
View File
@@ -4,7 +4,7 @@
#define JUNGFRAUJOCH_FPGAACQUISITIONDEVICE_H
#include "AcquisitionDevice.h"
#include "../fpga/pcie_driver/ActionConfig.h"
#include "../fpga/include/jfjoch_fpga.h"
class FPGAAcquisitionDevice : public AcquisitionDevice {
uint16_t data_collection_id = 0;
@@ -29,9 +29,8 @@ class FPGAAcquisitionDevice : public AcquisitionDevice {
volatile bool stop_work_requests = false;
void SendWorkRequestThread();
virtual void HW_LoadCalibration(uint32_t modules, uint32_t storage_cells) = 0;
virtual void HW_LoadIntegrationMap(uint32_t modules) = 0;
virtual void HW_LoadInternalGeneratorFrame(uint32_t modules) = 0;
virtual void HW_LoadCalibration(const LoadCalibrationConfig &config) = 0;
void LoadCalibration(uint32_t handle);
virtual bool HW_ReadMailbox(uint32_t *values) = 0;
virtual bool HW_SendWorkRequest(uint32_t handle) = 0;
virtual void HW_SetSpotFinderParameters(const SpotFinderParameters &params) = 0;
@@ -57,7 +56,7 @@ public:
void SetInternalGeneratorFrameForAllModules(const std::vector<uint16_t> &v);
void SetInternalGeneratorFrame();
std::vector<uint16_t> GetInternalGeneratorFrame() const override;
void SetSpotFinderParameters(int16_t count_threshold, double snr_threshold) override;
void SetSpotFinderParameters(int32_t count_threshold, float snr_threshold) override;
AcquisitionDeviceSource GetDataSource() override;
void SetDefaultDataSource(AcquisitionDeviceSource id) override;
uint32_t GetExpectedDescriptorsPerModule() const override;
+220 -204
View File
@@ -42,8 +42,7 @@ HLSSimulatedDevice::HLSSimulatedDevice(uint16_t data_stream, size_t in_frame_buf
max_modules = MAX_MODULES_FPGA;
MapBuffersStandard(in_frame_buffer_size_modules,
(3 + 3 * 16) * max_modules + 2, numa_node);
MapBuffersStandard(in_frame_buffer_size_modules, numa_node);
auto in_mem_location32 = (uint32_t *) dma_address_table.data();
@@ -142,35 +141,40 @@ void HLSSimulatedDevice::FPGA_StartAction(const DiffractionExperiment &experimen
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();
if (experiment.IsUsingInternalPacketGen()) {
data_source = STREAM_MERGE_SRC_FRAME_GEN;
auto ret = frame_generator(din_frame_generator,
hbm.data(),
hbm.data(),
hbm_if_size,
experiment.GetFrameNum() + DELAY_FRAMES_STOP_AND_QUIT + 1,
experiment.GetModulesNum(data_stream),
mac_addr,
mac_addr,
ipv4_addr,
ipv4_addr,
INT_PKT_GEN_BUNCHID,
INT_PKT_GEN_EXPTTIME,
INT_PKT_GEN_DEBUG,
cancel_data_collection);
if (ret)
throw JFJochException(JFJochExceptionCategory::AcquisitionDeviceError,
"Error running internal packet generator");
} else {
data_source = STREAM_MERGE_SRC_100G;
}
action_thread = std::thread(&HLSSimulatedDevice::HLSMainThread, this );
}
void HLSSimulatedDevice::FrameGeneratorFuture(FrameGeneratorConfig config) {
frame_generator(din_frame_generator,
hbm.data(),
hbm.data(),
hbm_if_size,
config.frames,
config.modules,
mac_addr,
config.dest_mac_addr,
ipv4_addr,
config.dest_ipv4_addr,
config.bunchid,
config.exptime,
config.debug,
cancel_data_collection);
}
void HLSSimulatedDevice::HW_RunInternalGenerator(const FrameGeneratorConfig &config) {
frame_generator_future = std::async(std::launch::async, &HLSSimulatedDevice::FrameGeneratorFuture, this, config);
}
void HLSSimulatedDevice::FPGA_EndAction() {
if (action_thread.joinable())
action_thread.join();
@@ -189,10 +193,11 @@ bool HLSSimulatedDevice::HW_ReadMailbox(uint32_t *values) {
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) {
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));
@@ -215,6 +220,12 @@ bool HLSSimulatedDevice::HW_SendWorkRequest(uint32_t handle) {
return true;
}
inline uint32_t float2uint(float f) {
float_uint32 fu;
fu.f = f;
return fu.u;
}
void HLSSimulatedDevice::HLSMainThread() {
uint64_t counter_hbm;
uint64_t counter_host;
@@ -273,85 +284,135 @@ void HLSSimulatedDevice::HLSMainThread() {
hls::stream<ap_uint<512>> spot_finder_result_1;
hls::stream<ap_uint<UDP_METADATA_STREAM_WIDTH> > udp_metadata;
ap_uint<1> idle_data_collection;
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;
if (data_source == STREAM_MERGE_SRC_FRAME_GEN) {
while (!din_frame_generator.empty())
stream_merge(din_eth, din_eth_4x10G, din_frame_generator, network0, data_source);
} else if (data_source == STREAM_MERGE_SRC_100G) {
while (!din_eth.empty())
stream_merge(din_eth, din_eth_4x10G, din_frame_generator, network0, data_source);
} else if (data_source == STREAM_MERGE_SRC_4x10G) {
while (!din_eth_4x10G.empty())
stream_merge(din_eth, din_eth_4x10G, din_frame_generator, network0, data_source);
}
volatile bool done = false;
volatile bool udp_done = false; // done AND udp_idle
volatile bool sls_done = false; // done AND sls_idle
while(!network0.empty())
ethernet(network0, ip1, arp1, mac_addr, eth_packets, clear_counters);
// Sent gratuitous ARP message
arp(arp1, dout_eth, mac_addr, ipv4_addr, 1, 1);
while(!ip1.empty())
ipv4(ip1, udp1, icmp1, ipv4_addr);
Logger logger_hls("HLS");
arp(arp1,
dout_eth,
mac_addr,
ipv4_addr,
1, run_data_collection);
volatile rcv_state_t state = RCV_INIT;
// Start data collection
data_collection_fsm(raw0, raw1,
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);
while (!arp1.empty()) {
arp(arp1,
dout_eth,
mac_addr,
ipv4_addr,
1, run_data_collection);
}
run_data_collection = 0;
data_collection_fsm(raw0, raw1,
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);
// reset static counter
arp(arp1,
dout_eth,
mac_addr,
ipv4_addr,
0, run_data_collection);
hls_cores.emplace_back([&] {
while (!udp_done) {
if (din_eth.empty() && din_eth_4x10G.empty() && din_frame_generator.empty())
std::this_thread::sleep_for(std::chrono::microseconds(10));
else
stream_merge(din_eth, din_eth_4x10G, din_frame_generator, network0, data_source);
}
logger_hls.Info("Stream_merge done");
});
while(!icmp1.empty())
icmp(icmp1, dout_eth, icmp_packets, clear_counters);
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");
});
while (!udp1.empty())
udp(udp1, udp2, udp_metadata, udp_packets, clear_counters);
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");
});
while (!udp2.empty())
sls_detector(udp2, udp_metadata, raw0, addr0, sls_packets, udp_eth_err, udp_len_err, clear_counters);
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, raw0, addr0, sls_packets, udp_eth_err, udp_len_err, clear_counters, sls_idle);
}
sls_done = true;
logger_hls.Info("sls_detector done");
});
// 1. Parse incoming UDP packets
idle_data_collection = 0;
hls_cores.emplace_back([&] {
while ((idle_data_collection == 0) || (!raw0.empty())) {
while ((state != RCV_WAIT_FOR_START) || (idle_data_collection.read() == 0) || (!raw0.empty())) {
data_collection_fsm(raw0, raw1,
addr0, addr1,
run_data_collection,
cancel_data_collection,
idle_data_collection,
cfg.mode,
cfg.one_over_energy,
float2uint(cfg.energy_kev),
cfg.nframes,
cfg.nmodules,
cfg.nstorage_cells,
cfg.nsummation);
run_data_collection = 0;
cfg.nsummation,
state);
}
done = true;
logger_hls.Info("data collection done");
});
// 2. Cache images in HBM
hls_cores.emplace_back([&] { save_to_hbm(raw1, converted_1, addr1, compl0, hbm_handles,
datamover_out_hbm_0.GetDataStream(), datamover_out_hbm_1.GetDataStream(),
datamover_out_hbm_0.GetCtrlStream(), datamover_out_hbm_1.GetCtrlStream(),
hbm_if_size);});
save_to_hbm_idle, hbm_if_size);});
hls_cores.emplace_back([&] {frame_summation_reorder_compl(converted_1, converted_2, compl0, compl1);});
hls_cores.emplace_back([&] { load_from_hbm(converted_2, converted_3, compl1, compl2, hbm_handles,
datamover_in_hbm_0.GetDataStream(), datamover_in_hbm_1.GetDataStream(),
datamover_in_hbm_0.GetCtrlStream(), datamover_in_hbm_1.GetCtrlStream(),
hbm_if_size);});
load_to_hbm_idle, hbm_if_size);});
hls_cores.emplace_back([&] { pedestal(converted_3, converted_3a, compl2, compl2a,
hbm.data(),
@@ -393,126 +454,139 @@ void HLSSimulatedDevice::HLSMainThread() {
hbm_if_size); });
// 6. Frame summation
hls_cores.emplace_back([&] { frame_summation(converted_6, stream_768_0, compl5, compl6);});
hls_cores.emplace_back([&] { frame_summation(converted_6, stream_768_0, compl5, compl6, frame_summation_idle);});
// 7. Integration of pixels
hls_cores.emplace_back([&] { integration(stream_768_0, stream_768_1, integration_result_0, compl6, compl7,
hbm.data(), hbm.data(), hbm.data(), hbm.data(), hbm_if_size);});
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);});
// 8. Spot finding
hls_cores.emplace_back([&] { spot_finder(stream_768_1, stream_768_2, spot_finder_result_0, count_threshold, snr_threshold);});
ap_uint<32> tmp_snr_threshold = float2uint(snr_threshold);
hls_cores.emplace_back([&] { spot_finder(stream_768_1, stream_768_2, spot_finder_result_0,
count_threshold,tmp_snr_threshold);});
hls_cores.emplace_back([&] { axis_32_to_512(spot_finder_result_0, spot_finder_result_1);});
// 9. Reduce/extend 24-bit stream
hls_cores.emplace_back([&] { stream_24bit_conv(stream_768_2, converted_7);});
hls_cores.emplace_back([&] { stream_24bit_conv(stream_768_2, converted_7, stream_conv_idle);});
// 10. Prepare data to write to host memory
hls_cores.emplace_back([&] {
ap_uint<3> state;
host_writer(converted_7, adu_histo_result, integration_result_1, spot_finder_result_1,
compl7, datamover_out.GetDataStream(),
datamover_out.GetCtrlStream(), work_request_stream, completion_stream,
dma_address_table.data(), packets_processed, host_writer_idle);});
dma_address_table.data(), packets_processed, host_writer_idle, cancel_data_collection, state);});
for (auto &i : hls_cores)
i.join();
if (!din_eth.empty())
throw std::runtime_error("din_eth queue not empty");
if (frame_generator_future.valid())
frame_generator_future.get();
if (!addr1.empty())
throw std::runtime_error("Addr1 queue not empty");
// reset static counter
arp(arp1, dout_eth, mac_addr, ipv4_addr, 0, 1);
try {
while (!din_eth.empty())
din_eth.read();
if (!addr2.empty())
throw std::runtime_error("Addr2 queue not empty");
if (!addr1.empty())
throw std::runtime_error("Addr1 queue not empty");
if (!addr3.empty())
throw std::runtime_error("Addr3 queue not empty");
if (!addr2.empty())
throw std::runtime_error("Addr2 queue not empty");
if (!raw1.empty())
throw std::runtime_error("Raw1 queue not empty");
if (!addr3.empty())
throw std::runtime_error("Addr3 queue not empty");
if (!raw2.empty())
throw std::runtime_error("Raw2 queue not empty");
if (!raw1.empty())
throw std::runtime_error("Raw1 queue not empty");
if (!raw3.empty())
throw std::runtime_error("Raw3 queue not empty");
if (!raw2.empty())
throw std::runtime_error("Raw2 queue not empty");
if (!converted_0.empty())
throw std::runtime_error("Converted_0 queue not empty");
if (!raw3.empty())
throw std::runtime_error("Raw3 queue not empty");
if (!converted_1.empty())
throw std::runtime_error("Converted_1 queue not empty");
if (!converted_0.empty())
throw std::runtime_error("Converted_0 queue not empty");
if (!converted_2.empty())
throw std::runtime_error("Converted_2 queue not empty");
if (!converted_1.empty())
throw std::runtime_error("Converted_1 queue not empty");
if (!converted_3.empty())
throw std::runtime_error("Converted_3 queue not empty");
if (!converted_2.empty())
throw std::runtime_error("Converted_2 queue not empty");
if (!converted_4.empty())
throw std::runtime_error("Converted_4 queue not empty");
if (!converted_3.empty())
throw std::runtime_error("Converted_3 queue not empty");
if (!converted_5.empty())
throw std::runtime_error("Converted_5 queue not empty");
if (!converted_4.empty())
throw std::runtime_error("Converted_4 queue not empty");
if (!converted_6.empty())
throw std::runtime_error("Converted_6 queue not empty");
if (!converted_5.empty())
throw std::runtime_error("Converted_5 queue not empty");
if (!converted_7.empty())
throw std::runtime_error("Converted_7 queue not empty");
if (!converted_6.empty())
throw std::runtime_error("Converted_6 queue not empty");
if (!converted_8.empty())
throw std::runtime_error("Converted_8 queue not empty");
if (!converted_7.empty())
throw std::runtime_error("Converted_7 queue not empty");
if (!compl0.empty())
throw std::runtime_error("Compl0 queue not empty");
if (!converted_8.empty())
throw std::runtime_error("Converted_8 queue not empty");
if (!compl1.empty())
throw std::runtime_error("Compl1 queue not empty");
if (!compl0.empty())
throw std::runtime_error("Compl0 queue not empty");
if (!compl2.empty())
throw std::runtime_error("Compl2 queue not empty");
if (!compl1.empty())
throw std::runtime_error("Compl1 queue not empty");
if (!compl3.empty())
throw std::runtime_error("Compl3 queue not empty");
if (!compl2.empty())
throw std::runtime_error("Compl2 queue not empty");
if (!compl4.empty())
throw std::runtime_error("Compl4 queue not empty");
if (!compl3.empty())
throw std::runtime_error("Compl3 queue not empty");
if (!compl5.empty())
throw std::runtime_error("Compl5 queue not empty");
if (!compl4.empty())
throw std::runtime_error("Compl4 queue not empty");
if (!compl6.empty())
throw std::runtime_error("Compl6 queue not empty");
if (!compl5.empty())
throw std::runtime_error("Compl5 queue not empty");
if (!compl7.empty())
throw std::runtime_error("Compl7 queue not empty");
if (!compl6.empty())
throw std::runtime_error("Compl6 queue not empty");
if (!stream_768_0.empty())
throw std::runtime_error("Stream_768_0 queue not empty");
if (!compl7.empty())
throw std::runtime_error("Compl7 queue not empty");
if (!stream_768_1.empty())
throw std::runtime_error("Stream_768_1 queue not empty");
if (!stream_768_0.empty())
throw std::runtime_error("Stream_768_0 queue not empty");
if (!stream_768_2.empty())
throw std::runtime_error("Stream_768_2 queue not empty");
if (!stream_768_1.empty())
throw std::runtime_error("Stream_768_1 queue not empty");
if (!hbm_handles.empty())
throw std::runtime_error("Handles queue not empty");
if (!stream_768_2.empty())
throw std::runtime_error("Stream_768_2 queue not empty");
if (!integration_result_0.empty())
throw std::runtime_error("Integration result queue not empty");
if (!hbm_handles.empty())
throw std::runtime_error("Handles queue not empty");
if (!integration_result_1.empty())
throw std::runtime_error("Integration result queue not empty");
if (!integration_result_0.empty())
throw std::runtime_error("Integration result queue not empty");
if (!datamover_in.GetDataStream().empty())
throw std::runtime_error("Datamover queue is not empty");
if (!integration_result_1.empty())
throw std::runtime_error("Integration result queue not empty");
while (!datamover_out.IsIdle())
std::this_thread::sleep_for(std::chrono::milliseconds(100));
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);
@@ -525,77 +599,19 @@ void HLSSimulatedDevice::HW_GetStatus(DataCollectionStatus *status) const {
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;
}
void HLSSimulatedDevice::HW_LoadCalibration(uint32_t modules, uint32_t storage_cells) {
if (logger)
logger->Info("Load calibration start");
int ret = load_calibration(hbm.data(),
hbm.data(),
modules,
storage_cells,
void HLSSimulatedDevice::HW_LoadCalibration(const LoadCalibrationConfig &config) {
int ret = load_calibration(hbm.data(), hbm.data(),
config,
hbm_if_size,
LOAD_CALIBRATION_DEST_CALIB,
datamover_in.GetCtrlStream(),
datamover_in.GetDataStream(),
dma_address_table.data());
if (ret)
throw JFJochException(JFJochExceptionCategory::AcquisitionDeviceError,
"Error in loading calibration");
if (logger)
logger->Info("Load calibration done");
if (!datamover_in.GetDataStream().empty())
throw std::runtime_error("Datamover queue is not empty");
}
void HLSSimulatedDevice::HW_LoadIntegrationMap(uint32_t modules) {
if (logger)
logger->Info("Load calibration start");
int ret = load_calibration(hbm.data(),
hbm.data(),
modules,
0,
hbm_if_size,
LOAD_CALIBRATION_DEST_INTEGRATION,
datamover_in.GetCtrlStream(),
datamover_in.GetDataStream(),
dma_address_table.data());
if (ret)
throw JFJochException(JFJochExceptionCategory::AcquisitionDeviceError,
"Error in loading calibration");
if (logger)
logger->Info("Load integration_map");
if (!datamover_in.GetDataStream().empty())
throw std::runtime_error("Datamover queue is not empty");
}
void HLSSimulatedDevice::HW_LoadInternalGeneratorFrame(uint32_t modules) {
if (logger)
logger->Info("Load to frame generator");
int ret = load_calibration(hbm.data(),
hbm.data(),
modules,
0,
hbm_if_size,
LOAD_CALIBRATION_DEST_FRAME_GEN,
datamover_in.GetCtrlStream(),
datamover_in.GetDataStream(),
dma_address_table.data());
if (ret)
throw JFJochException(JFJochExceptionCategory::AcquisitionDeviceError,
"Error in loading calibration");
if (logger)
logger->Info("Load to frame generator done");
"Error in loading calibration " + std::to_string(ret));
if (!datamover_in.GetDataStream().empty())
throw std::runtime_error("Datamover queue is not empty");
@@ -612,4 +628,4 @@ void HLSSimulatedDevice::HW_SetDataSource(uint32_t val) {
uint32_t HLSSimulatedDevice::HW_GetDataSource() {
return data_source;
}
}
+9 -6
View File
@@ -19,9 +19,11 @@ class HLSSimulatedDevice : public FPGAAcquisitionDevice {
AXI_STREAM din_frame_generator;
AXI_STREAM dout_eth;
uint32_t run_counter = 0;
ap_uint<2> data_source = STREAM_MERGE_SRC_100G;
ap_int<16> count_threshold = INT16_MAX;
ap_uint<8> snr_threshold = 0;
ap_int<32> count_threshold = -1;
float snr_threshold = 0;
DataCollectionConfig cfg;
@@ -37,6 +39,7 @@ class HLSSimulatedDevice : public FPGAAcquisitionDevice {
uint32_t completion_count;
std::thread action_thread;
std::future<void> frame_generator_future;
Datamover<512> datamover_in;
Datamover<512> datamover_out;
@@ -59,14 +62,14 @@ class HLSSimulatedDevice : public FPGAAcquisitionDevice {
bool HW_IsIdle() const override;
bool HW_ReadMailbox(uint32_t *values) override;
bool HW_SendWorkRequest(uint32_t handle) override;
void HW_LoadCalibration(uint32_t modules, uint32_t storage_cells) override;
void HW_LoadIntegrationMap(uint32_t modules) override;
void HW_LoadInternalGeneratorFrame(uint32_t modules) override;
void HW_LoadCalibration(const LoadCalibrationConfig &config) override;
void HW_GetStatus(DataCollectionStatus *status) const override;
void HW_SetSpotFinderParameters(const SpotFinderParameters &params) override;
uint32_t HW_GetDataSource() override;
void HW_SetDataSource(uint32_t val) override;
void HLSMainThread() ;
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;
+7 -20
View File
@@ -44,15 +44,10 @@ bool PCIExpressDevice::HW_SendWorkRequest(uint32_t handle) {
void PCIExpressDevice::FPGA_StartAction(const DiffractionExperiment &experiment) {
dev.Start();
if (experiment.IsUsingInternalPacketGen()) {
FrameGeneratorConfig config{};
config.frames = experiment.GetFrameNum() + DELAY_FRAMES_STOP_AND_QUIT + 1;
config.modules = experiment.GetModulesNum(data_stream);
}
config.dest_mac_addr = dev.GetMACAddress();
config.dest_ipv4_addr = dev.GetIPv4Address();
dev.RunFrameGenerator(config);
}
void PCIExpressDevice::HW_RunInternalGenerator(const FrameGeneratorConfig &config) {
dev.RunFrameGenerator(config);
}
void PCIExpressDevice::FPGA_EndAction() {
@@ -107,18 +102,6 @@ std::string PCIExpressDevice::GetIPv4Address() const {
return IPv4AddressToStr(dev.GetIPv4Address());
}
void PCIExpressDevice::HW_LoadCalibration(uint32_t in_modules, uint32_t in_storage_cells) {
dev.LoadCalibration(in_modules, in_storage_cells);
}
void PCIExpressDevice::HW_LoadIntegrationMap(uint32_t in_modules) {
dev.LoadIntegrationMap(in_modules);
}
void PCIExpressDevice::HW_LoadInternalGeneratorFrame(uint32_t in_modules) {
dev.LoadInternalGeneratorFrame(in_modules);
}
void PCIExpressDevice::HW_SetSpotFinderParameters(const SpotFinderParameters &params) {
dev.SetSpotFinderParameters(params);
}
@@ -139,3 +122,7 @@ void PCIExpressDevice::HW_SetDataSource(uint32_t val) {
return dev.SetDataSource(val);
}
void PCIExpressDevice::HW_LoadCalibration(const LoadCalibrationConfig &config) {
dev.LoadCalibration(config);
}
+2 -3
View File
@@ -9,20 +9,19 @@
class PCIExpressDevice : public FPGAAcquisitionDevice {
JungfraujochDevice dev;
void HW_LoadCalibration(const LoadCalibrationConfig &config) override;
bool HW_ReadMailbox(uint32_t *values) override;
bool HW_SendWorkRequest(uint32_t handle) override;
void FPGA_StartAction(const DiffractionExperiment &experiment) override;
bool HW_IsIdle() const final;
void HW_WriteActionRegister(const DataCollectionConfig *job) override;
void HW_ReadActionRegister(DataCollectionConfig *job) override;
void HW_LoadCalibration(uint32_t modules, uint32_t storage_cells) override;
void HW_LoadIntegrationMap(uint32_t modules) override;
void HW_LoadInternalGeneratorFrame(uint32_t modules) override;
void HW_SetSpotFinderParameters(const SpotFinderParameters &params) override;
uint32_t HW_GetDataSource() override;
void HW_SetDataSource(uint32_t val) override;
void FPGA_EndAction() override;
uint32_t GetNumKernelBuffers() const;
void HW_RunInternalGenerator(const FrameGeneratorConfig &config) override;
public:
explicit PCIExpressDevice(uint16_t data_stream);
PCIExpressDevice(uint16_t data_stream, uint16_t pci_slot);
-2
View File
@@ -1,5 +1,3 @@
ADD_SUBDIRECTORY(pistache)
AUX_SOURCE_DIRECTORY(gen/model MODEL_SOURCES)
ADD_LIBRARY(JFJochAPI STATIC ${MODEL_SOURCES} gen/api/DefaultApi.cpp gen/api/DefaultApi.h)
+88 -21
View File
@@ -38,22 +38,29 @@ inline org::openapitools::server::model::Spot_finding_settings Convert(const Spo
inline org::openapitools::server::model::Measurement_statistics Convert(const MeasurementStatistics &input) {
org::openapitools::server::model::Measurement_statistics ret{};
ret.setFilePrefix(input.file_prefix);
if (!input.file_prefix.empty())
ret.setFilePrefix(input.file_prefix);
ret.setImagesExpected(input.images_expected);
ret.setImagesCollected(input.images_collected);
ret.setImagesSent(input.images_sent);
ret.setMaxImageNumberSent(input.max_image_number_sent);
ret.setCollectionEfficiency(input.collection_efficiency);
if (input.collection_efficiency >= 0.0)
ret.setCollectionEfficiency(input.collection_efficiency);
ret.setCompressionRatio(input.compression_ratio);
ret.setCancelled(input.cancelled);
ret.setMaxReceiverDelay(input.max_receive_delay);
ret.setIndexingRate(input.indexing_rate);
ret.setDetectorWidth(input.detector_width);
ret.setDetectorHeight(input.detector_height);
ret.setDetectorPixelDepth(input.detector_pixel_depth);
ret.setBkgEstimate(input.bkg_estimate);
if (input.indexing_rate >= 0.0)
ret.setIndexingRate(input.indexing_rate);
if (input.bkg_estimate >= 0.0)
ret.setBkgEstimate(input.bkg_estimate);
return ret;
}
@@ -69,6 +76,8 @@ inline DetectorSettings Convert(const org::openapitools::server::model::Detector
ret.use_internal_packet_generator = input.isInternalFrameGenerator();
ret.collect_raw_data = input.isCollectRawData();
ret.fixed_gain_g1 = input.isFixedGainG1();
ret.use_gain_hg0 = input.isUseGainHg0();
if (input.pedestalG0FramesIsSet())
ret.pedestal_g0_frames = input.getPedestalG0Frames();
@@ -91,7 +100,8 @@ inline org::openapitools::server::model::Detector_settings Convert(const Detecto
ret.setStorageCellCount(input.storage_cell_count);
ret.setInternalFrameGenerator(input.use_internal_packet_generator);
ret.setCollectRawData(input.collect_raw_data);
ret.setFixedGainG1(input.fixed_gain_g1);
ret.setUseGainHg0(input.use_gain_hg0);
ret.setPedestalG0Frames(input.pedestal_g0_frames.value());
ret.setPedestalG1Frames(input.pedestal_g1_frames.value());
ret.setPedestalG2Frames(input.pedestal_g2_frames.value());
@@ -125,10 +135,8 @@ inline org::openapitools::server::model::Broker_status Convert(const BrokerStatu
}
if (input.progress.has_value())
ret.setProgress(input.progress.value());
if (input.indexing_rate.has_value())
if (input.indexing_rate.has_value() && (input.indexing_rate >= 0.0))
ret.setIndexingRate(input.indexing_rate.value());
if (input.receiver_send_buffers_avail.has_value())
ret.setReceiverSendBuffersAvail(input.receiver_send_buffers_avail.value());
return ret;
}
@@ -274,22 +282,32 @@ inline DatasetSettings Convert(const org::openapitools::server::model::Dataset_s
if (input.transmissionIsSet())
ret.attenuator_transmission = input.getTransmission();
if (input.omegaIsSet()) {
ret.omega_step = input.getOmega().getStep();
ret.omega_start = input.getOmega().getStart();
if (input.getOmega().getVector().size() == 3) {
auto v = input.getOmega().getVector();
ret.omega_axis = Coord(v[0], v[1], v[2]);
} else
ret.omega_axis = Coord(0, 0, 0);
}
if (input.roiSumAreaIsSet()) {
ret.roi_sum_area = ROIRectangle{
.x_min = static_cast<size_t>(input.getRoiSumArea().getXMin()),
.x_max = static_cast<size_t>(input.getRoiSumArea().getXMax()),
.y_min = static_cast<size_t>(input.getRoiSumArea().getYMin()),
.y_max = static_cast<size_t>(input.getRoiSumArea().getYMax())
};
}
ret.space_group_number = input.spaceGroupNumberIsSet() ? input.getSpaceGroupNumber() : 0;
ret.sample_name = input.getSampleName();
ret.header_appendix = input.getHeaderAppendix();
ret.image_appendix = input.getImageAppendix();
ret.save_calibration = input.saveCalibrationIsSet() && input.isSaveCalibration();
return ret;
}
template <class T>
void ProcessOutput(const T& output, Pistache::Http::ResponseWriter &response) {
std::stringstream s;
assert(output.validate(s));
nlohmann::json j;
to_json(j, output);
response.send(Pistache::Http::Code::Ok, j.dump(), MIME(Application, Json));
}
JFJochBrokerHttp::JFJochBrokerHttp(const DiffractionExperiment &experiment, std::shared_ptr<Pistache::Rest::Router> &rtr)
: DefaultApi(rtr) {
@@ -314,6 +332,7 @@ JFJochServices &JFJochBrokerHttp::Services() {
void JFJochBrokerHttp::cancel_post(Pistache::Http::ResponseWriter &response) {
state_machine.Cancel();
response.send(Pistache::Http::Code::Ok);
}
void JFJochBrokerHttp::deactivate_post(Pistache::Http::ResponseWriter &response) {
@@ -408,8 +427,11 @@ void JFJochBrokerHttp::config_spot_finding_put(
response.send(Pistache::Http::Code::Ok);
}
void JFJochBrokerHttp::plot_adu_histogram_get(Pistache::Http::ResponseWriter &response) {
PlotRequest req{.type = PlotType::ADUHistorgram};
void JFJochBrokerHttp::plot_saturated_pixel_post(const org::openapitools::server::model::Plot_request &plotRequest,
Pistache::Http::ResponseWriter &response) {
PlotRequest req{.type = PlotType::SaturatedPixels, .binning = 0};
if (plotRequest.binningIsSet())
req.binning = plotRequest.getBinning();
auto plot = state_machine.GetPlots(req);
ProcessOutput(Convert(plot), response);
}
@@ -539,4 +561,49 @@ void JFJochBrokerHttp::GetStaticFile(const Pistache::Rest::Request &request, Pis
JFJochBrokerHttp &JFJochBrokerHttp::FrontendDirectory(const std::string &directory) {
frontend_directory = directory;
return *this;
}
void JFJochBrokerHttp::plot_error_pixel_post(const org::openapitools::server::model::Plot_request &plotRequest,
Pistache::Http::ResponseWriter &response) {
PlotRequest req{.type = PlotType::ErrorPixels, .binning = 0};
if (plotRequest.binningIsSet())
req.binning = plotRequest.getBinning();
auto plot = state_machine.GetPlots(req);
ProcessOutput(Convert(plot), response);
}
void JFJochBrokerHttp::plot_strong_pixel_post(const org::openapitools::server::model::Plot_request &plotRequest,
Pistache::Http::ResponseWriter &response) {
PlotRequest req{.type = PlotType::StrongPixels, .binning = 0};
if (plotRequest.binningIsSet())
req.binning = plotRequest.getBinning();
auto plot = state_machine.GetPlots(req);
ProcessOutput(Convert(plot), response);
}
void JFJochBrokerHttp::plot_image_collection_efficiency_post(
const org::openapitools::server::model::Plot_request &plotRequest, Pistache::Http::ResponseWriter &response) {
PlotRequest req{.type = PlotType::ImageCollectionEfficiency, .binning = 0};
if (plotRequest.binningIsSet())
req.binning = plotRequest.getBinning();
auto plot = state_machine.GetPlots(req);
ProcessOutput(Convert(plot), response);
}
void JFJochBrokerHttp::plot_receiver_delay_post(const org::openapitools::server::model::Plot_request &plotRequest,
Pistache::Http::ResponseWriter &response) {
PlotRequest req{.type = PlotType::ReceiverDelay, .binning = 0};
if (plotRequest.binningIsSet())
req.binning = plotRequest.getBinning();
auto plot = state_machine.GetPlots(req);
ProcessOutput(Convert(plot), response);
}
void JFJochBrokerHttp::plot_roi_sum_post(const org::openapitools::server::model::Plot_request &plotRequest,
Pistache::Http::ResponseWriter &response) {
PlotRequest req{.type = PlotType::ROISum, .binning = 0};
if (plotRequest.binningIsSet())
req.binning = plotRequest.getBinning();
auto plot = state_machine.GetPlots(req);
ProcessOutput(Convert(plot), response);
}
+27 -1
View File
@@ -38,7 +38,21 @@ class JFJochBrokerHttp : public org::openapitools::server::api::DefaultApi {
void config_spot_finding_put(const org::openapitools::server::model::Spot_finding_settings &spotFindingSettings,
Pistache::Http::ResponseWriter &response) override;
void plot_adu_histogram_get(Pistache::Http::ResponseWriter &response) override;
void plot_roi_sum_post(const org::openapitools::server::model::Plot_request &plotRequest,
Pistache::Http::ResponseWriter &response) override;
void plot_saturated_pixel_post(const org::openapitools::server::model::Plot_request &plotRequest,
Pistache::Http::ResponseWriter &response) override;
void plot_error_pixel_post(const org::openapitools::server::model::Plot_request &plotRequest,
Pistache::Http::ResponseWriter &response) override;
void plot_strong_pixel_post(const org::openapitools::server::model::Plot_request &plotRequest,
Pistache::Http::ResponseWriter &response) override;
void plot_receiver_delay_post(const org::openapitools::server::model::Plot_request &plotRequest,
Pistache::Http::ResponseWriter &response) override;
void plot_image_collection_efficiency_post(const org::openapitools::server::model::Plot_request &plotRequest,
Pistache::Http::ResponseWriter &response) override;
void plot_bkg_estimate_post(const org::openapitools::server::model::Plot_request &plotRequest,
Pistache::Http::ResponseWriter &response) override;
@@ -77,6 +91,18 @@ class JFJochBrokerHttp : public org::openapitools::server::api::DefaultApi {
void GetStaticFile(const Pistache::Rest::Request &request, Pistache::Http::ResponseWriter response);
std::pair<Pistache::Http::Code, std::string> handleOperationException(const std::exception &ex) const noexcept override;
template <class T>
void ProcessOutput(const T& output, Pistache::Http::ResponseWriter &response) {
std::stringstream s;
if(!output.validate(s)) {
logger.Error(s.str());
response.send(Pistache::Http::Code::Internal_Server_Error, s.str(), MIME(Text, Plain));
}
nlohmann::json j;
to_json(j, output);
response.send(Pistache::Http::Code::Ok, j.dump(), MIME(Application, Json));
}
public:
JFJochBrokerHttp(const DiffractionExperiment& experiment, std::shared_ptr<Pistache::Rest::Router> &rtr);
void AddDetectorSetup(const DetectorSetup &setup);
+16 -1
View File
@@ -246,6 +246,16 @@ void ParseFacilityConfiguration(const nlohmann::json &input, const std::string&
experiment.InstrumentName(GET_STR(j, "instrument_name"));
experiment.InstrumentNameShort(GET_STR(j, "instrument_name_short"));
if (j.contains("omega_axis")) {
if (j["omega_axis"].is_array() && (j["omega_axis"].size() == 3))
experiment.DefaultOmegaAxis(Coord(j["omega_axis"][0].get<float>(),
j["omega_axis"][1].get<float>(),
j["omega_axis"][2].get<float>()));
else
throw JFJochException(JFJochExceptionCategory::InputParameterInvalid,
"omega_axis must be float array of 3");
}
experiment.PedestalG0Frames(GET_I64(j, "pedestal_g0_frames"));
experiment.PedestalG1Frames(GET_I64(j, "pedestal_g1_frames"));
experiment.PedestalG2Frames(GET_I64(j, "pedestal_g2_frames"));
@@ -264,7 +274,7 @@ void ParseAcquisitionDeviceGroup(const nlohmann::json &input, const std::string&
const auto &j = input[tag];
std::string dev_type = GET_STR(j, "type");
bool use_4x10g = GET_BOOL(j, "use_4x10g", false);
int64_t buffer_size = GET_I64(j, "buffer_size", 1024);
int64_t dev_count = GET_I64(j, "count", 1);
@@ -284,6 +294,11 @@ void ParseAcquisitionDeviceGroup(const nlohmann::json &input, const std::string&
} else
throw JFJochException(JFJochExceptionCategory::InputParameterInvalid, "Device type unknown");
if (use_4x10g)
aq_devices.SetDefaultDataSource(AcquisitionDeviceSource::MAC_4x10G);
else
aq_devices.SetDefaultDataSource(AcquisitionDeviceSource::MAC_100G);
std::vector<std::string> ipv4_addr = GET_STR_ARR(j, "ipv4_addr");
if (ipv4_addr.size() != aq_devices.size())
throw JFJochException(JFJochExceptionCategory::InputParameterInvalid,
+1 -1
View File
@@ -7,7 +7,7 @@
#include "../common/DiffractionExperiment.h"
#include "JFJochBrokerHttp.h"
#include "../acquisition_device/AcquisitionDeviceGroup.h"
#include "../frame_serialize/ZMQPreviewPublisher.h"
#include "../frame_serialize/ZMQStream2PreviewPublisher.h"
DetectorGeometry ParseStandardDetectorGeometry(const nlohmann::json &j);
DetectorGeometry ParseCustomDetectorGeometry(const nlohmann::json &j);
+27 -20
View File
@@ -14,12 +14,13 @@ void JFJochServices::Start(const DiffractionExperiment& experiment, const JFCali
receiver->Start(experiment, &calibration);
else
receiver->Start(experiment, nullptr);
if (detector && !experiment.IsUsingInternalPacketGen()) {
logger.Info(" ... detector start");
detector->Start(experiment);
}
}
if (detector && !experiment.IsUsingInternalPacketGen()) {
logger.Info(" ... detector start");
detector->Start(experiment);
}
logger.Info(" Done!");
}
@@ -37,7 +38,7 @@ void JFJochServices::On(const DiffractionExperiment &x) {
logger.Info(" ... done");
}
JFJochServicesOutput JFJochServices::Stop(const JFCalibration &calibration) {
JFJochServicesOutput JFJochServices::Stop() {
JFJochServicesOutput ret;
std::unique_ptr<JFJochException> exception;
@@ -49,8 +50,8 @@ JFJochServicesOutput JFJochServices::Stop(const JFCalibration &calibration) {
logger.Info(" ... Receiver efficiency: {} % Max delay: {} Compression ratio {}x",
static_cast<int>(ret.receiver_output.efficiency * 100.0),
ret.receiver_output.max_receive_delay,
static_cast<int>(std::round(ret.receiver_output.compressed_ratio)));
ret.receiver_output.status.max_receive_delay,
static_cast<int>(std::round(ret.receiver_output.status.compressed_ratio)));
if (ret.receiver_output.efficiency < 1.0) {
for (int i = 0; i < ret.receiver_output.received_packets.size(); i++) {
if (ret.receiver_output.received_packets[i] != ret.receiver_output.expected_packets[i])
@@ -63,20 +64,25 @@ JFJochServicesOutput JFJochServices::Stop(const JFCalibration &calibration) {
exception = std::make_unique<JFJochException>(e);
}
logger.Info("Receiver finished with success");
}
if (detector) {
logger.Info("Stopping detector");
try {
if (detector) {
logger.Info("Stopping detector");
try {
detector->Stop();
logger.Info(" ... done");
} catch (JFJochException &e) {
logger.Error(" ... finished with error {}", e.what());
exception = std::make_unique<JFJochException>(e);
detector->Stop();
logger.Info(" ... done");
} catch (JFJochException &e) {
logger.Error(" ... finished with error {}", e.what());
exception = std::make_unique<JFJochException>(e);
}
}
} else {
logger.Info("No receiver - sleeping for 30 seconds");
std::this_thread::sleep_for(std::chrono::seconds(30));
logger.Info("Sleep done");
}
if (exception)
throw JFJochException(*exception);
@@ -84,10 +90,11 @@ JFJochServicesOutput JFJochServices::Stop(const JFCalibration &calibration) {
}
void JFJochServices::Cancel() {
if (detector)
detector->Stop();
if (receiver != nullptr)
if (receiver != nullptr) {
if (detector)
detector->Stop();
receiver->Cancel();
}
}
JFJochServices &JFJochServices::Receiver(JFJochReceiverService *input) {
@@ -135,6 +142,6 @@ void JFJochServices::SetSpotFindingSettings(const SpotFindingSettings &settings)
}
void JFJochServices::Trigger() {
if (detector)
if (detector && (receiver != nullptr))
detector->Trigger();
}
+1 -1
View File
@@ -23,7 +23,7 @@ public:
void On(const DiffractionExperiment& experiment);
void Off();
void Start(const DiffractionExperiment& experiment, const JFCalibration &calibration);
JFJochServicesOutput Stop(const JFCalibration &calibration);
JFJochServicesOutput Stop();
void Cancel();
void Trigger();
+148 -67
View File
@@ -24,11 +24,20 @@ void LoadDatasetSettings(DiffractionExperiment& experiment, const DatasetSetting
experiment.SampleName(settings.sample_name);
experiment.Compression(settings.compression);
experiment.SaveCalibration(settings.save_calibration);
experiment.OmegaStart(settings.omega_start).OmegaStep(settings.omega_step);
if (settings.omega_axis.Length() == 0.0f)
experiment.OmegaAxis();
else
experiment.OmegaAxis(settings.omega_axis);
experiment.ImageAppendix(settings.image_appendix);
experiment.HeaderAppendix(settings.header_appendix);
if (settings.summation == 0)
experiment.Summation(1);
else
experiment.Summation(settings.summation);
experiment.FPGAOutputMode(settings.fpga_pixel_output);
experiment.ROISummation(settings.roi_sum_area);
} catch (...) {
experiment = tmp;
throw;
@@ -52,6 +61,9 @@ void ApplyDetectorSettings(DiffractionExperiment& experiment, const DetectorSett
else
experiment.Mode(DetectorMode::Conversion);
experiment.UsingGainHG0(settings.use_gain_hg0);
experiment.FixedGainG1(settings.fixed_gain_g1);
if (settings.pedestal_g0_frames)
experiment.PedestalG0Frames(settings.pedestal_g0_frames.value());
if (settings.pedestal_g1_frames)
@@ -76,9 +88,9 @@ void ApplyRadialIntegrationSettings(DiffractionExperiment& experiment, const Rad
experiment.ApplyPolarizationCorr(false);
experiment.ApplySolidAngleCorr(settings.solid_angle_correction);
experiment.LowQForRadialInt_recipA(settings.low_q_recipA);
experiment.HighQForRadialInt_recipA(settings.high_q_recipA);
experiment.QSpacingForRadialInt_recipA(settings.q_spacing);
experiment.LowQForAzimInt_recipA(settings.low_q_recipA);
experiment.HighQForAzimInt_recipA(settings.high_q_recipA);
experiment.QSpacingForAzimInt_recipA(settings.q_spacing);
} catch (...) {
experiment = tmp;
throw;
@@ -91,32 +103,36 @@ data_processing_settings(DiffractionExperiment::DefaultDataProcessingSettings())
}
void JFJochStateMachine::ImportPedestalG0(const JFJochReceiverOutput &receiver_output) {
bool JFJochStateMachine::ImportPedestalG0(const JFJochReceiverOutput &receiver_output) {
if (receiver_output.pedestal_result.empty())
return;
return false;
if (receiver_output.pedestal_result.size() != experiment.GetModulesNum() * experiment.GetStorageCellNumber())
throw JFJochException(JFJochExceptionCategory::InputParameterInvalid, "Mismatch in pedestal output");
size_t gain_level = experiment.IsFixedGainG1() ? 1 : 0;
for (int s = 0; s < experiment.GetStorageCellNumber(); s++) {
for (int module = 0; module < experiment.GetModulesNum(); module++)
calibration->Pedestal(module, 0, s)
calibration->Pedestal(module, gain_level, s)
= receiver_output.pedestal_result[module + s * experiment.GetModulesNum()];
}
SetCalibrationStatistics(calibration->GetModuleStatistics());
return true;
}
void JFJochStateMachine::ImportPedestal(const JFJochReceiverOutput &receiver_output, size_t gain_level,
size_t storage_cell) {
bool JFJochStateMachine::ImportPedestalG1G2(const JFJochReceiverOutput &receiver_output, size_t gain_level,
size_t storage_cell) {
if (receiver_output.pedestal_result.empty())
return;
return false;
if (receiver_output.pedestal_result.size() != experiment.GetModulesNum() * experiment.GetStorageCellNumber())
if (receiver_output.pedestal_result.size() != experiment.GetModulesNum())
throw JFJochException(JFJochExceptionCategory::InputParameterInvalid, "Mismatch in pedestal output");
for (int i = 0; i < receiver_output.pedestal_result.size(); i++)
calibration->Pedestal(i, gain_level, storage_cell) = receiver_output.pedestal_result[i];
SetCalibrationStatistics(calibration->GetModuleStatistics());
return true;
}
void JFJochStateMachine::TakePedestalInternalAll(std::unique_lock<std::mutex> &ul) {
@@ -135,10 +151,11 @@ void JFJochStateMachine::TakePedestalInternalAll(std::unique_lock<std::mutex> &u
try {
TakePedestalInternalG0(ul);
for (int i = 0; i < experiment.GetStorageCellNumber(); i++) {
TakePedestalInternalG1(ul, i);
TakePedestalInternalG2(ul, i);
if (!experiment.IsFixedGainG1()) {
for (int i = 0; i < experiment.GetStorageCellNumber(); i++) {
TakePedestalInternalG1(ul, i);
TakePedestalInternalG2(ul, i);
}
}
} catch (const std::exception &e) {
logger.Error("Pedestal sequence error {}", e.what());
@@ -148,33 +165,45 @@ void JFJochStateMachine::TakePedestalInternalAll(std::unique_lock<std::mutex> &u
logger.Info("Pedestal sequence done");
}
void JFJochStateMachine::TakePedestalInternalG0(std::unique_lock<std::mutex> &ul) {
state = JFJochState::Pedestal;
DiffractionExperiment local_experiment(experiment);
local_experiment.Mode(DetectorMode::PedestalG0);
if (local_experiment.IsFixedGainG1())
local_experiment.Mode(DetectorMode::PedestalG1);
else
local_experiment.Mode(DetectorMode::PedestalG0);
if (local_experiment.GetStorageCellNumber() == 1)
local_experiment.StorageCellStart(15);
else
local_experiment.StorageCellStart(0);
if (!cancel_sequence && (local_experiment.GetPedestalG0Frames() > 0)) {
services.Start(local_experiment, *calibration);
services.Trigger();
ul.unlock();
// Allow to cancel/abort during the pedestal data collection
// Must ensure that while state is Pedestal, nothing can take lock for longer time, to avoid deadlock
auto pedestal_output = services.Stop(*calibration);
ul.lock();
// SetFullMeasurementOutput(pedestal_output);
ImportPedestalG0(pedestal_output.receiver_output);
if (cancel_sequence) {
state = JFJochState::Inactive;
return;
}
state = JFJochState::Idle;
if (local_experiment.GetPedestalG0Frames() == 0) {
state = JFJochState::Idle;
return;
}
state = JFJochState::Pedestal;
services.Start(local_experiment, *calibration);
services.Trigger();
ul.unlock();
// Allow to cancel/abort during the pedestal data collection
// Must ensure that while state is Pedestal, nothing can take lock for longer time, to avoid deadlock
auto pedestal_output = services.Stop();
ul.lock();
SetFullMeasurementOutput(pedestal_output);
if (ImportPedestalG0(pedestal_output.receiver_output))
state = JFJochState::Idle;
else
state = JFJochState::Inactive;
}
void JFJochStateMachine::TakePedestalInternalG1(std::unique_lock<std::mutex> &ul, int32_t storage_cell) {
state = JFJochState::Pedestal;
DiffractionExperiment local_experiment(experiment);
local_experiment.Mode(DetectorMode::PedestalG1);
@@ -183,23 +212,35 @@ void JFJochStateMachine::TakePedestalInternalG1(std::unique_lock<std::mutex> &ul
else
local_experiment.StorageCellStart(15);
if (!cancel_sequence && (local_experiment.GetPedestalG1Frames() > 0)) {
services.Start(local_experiment, *calibration);
services.Trigger();
ul.unlock();
// Allow to cancel/abort during the pedestal data collection
// Must ensure that while state is Pedestal, nothing can take lock for longer time, to avoid deadlock
auto pedestal_output = services.Stop(*calibration);
ul.lock();
// SetFullMeasurementOutput(pedestal_output);
ImportPedestal(pedestal_output.receiver_output, 1, storage_cell);
if (cancel_sequence) {
state = JFJochState::Inactive;
return;
}
state = JFJochState::Idle;
if (local_experiment.GetPedestalG1Frames() == 0) {
state = JFJochState::Idle;
return;
}
state = JFJochState::Pedestal;
services.Start(local_experiment, *calibration);
services.Trigger();
ul.unlock();
// Allow to cancel/abort during the pedestal data collection
// Must ensure that while state is Pedestal, nothing can take lock for longer time, to avoid deadlock
auto pedestal_output = services.Stop();
ul.lock();
SetFullMeasurementOutput(pedestal_output);
if (ImportPedestalG1G2(pedestal_output.receiver_output, 1, storage_cell))
state = JFJochState::Idle;
else
state = JFJochState::Inactive;
}
void JFJochStateMachine::TakePedestalInternalG2(std::unique_lock<std::mutex> &ul, int32_t storage_cell) {
state = JFJochState::Pedestal;
DiffractionExperiment local_experiment(experiment);
local_experiment.Mode(DetectorMode::PedestalG2);
@@ -208,19 +249,30 @@ void JFJochStateMachine::TakePedestalInternalG2(std::unique_lock<std::mutex> &ul
else
local_experiment.StorageCellStart(15);
if (!cancel_sequence && (local_experiment.GetPedestalG2Frames() > 0)) {
services.Start(local_experiment, *calibration);
services.Trigger();
ul.unlock();
// Allow to cancel/abort during the pedestal data collection
// Must ensure that while state is Pedestal, nothing can take lock for longer time, to avoid deadlock
auto pedestal_output = services.Stop(*calibration);
ul.lock();
// SetFullMeasurementOutput(pedestal_output);
ImportPedestal(pedestal_output.receiver_output, 2, storage_cell);
if (cancel_sequence) {
state = JFJochState::Inactive;
return;
}
state = JFJochState::Idle;
if (local_experiment.GetPedestalG2Frames() == 0) {
state = JFJochState::Idle;
return;
}
state = JFJochState::Pedestal;
services.Start(local_experiment, *calibration);
services.Trigger();
ul.unlock();
// Allow to cancel/abort during the pedestal data collection
// Must ensure that while state is Pedestal, nothing can take lock for longer time, to avoid deadlock
auto pedestal_output = services.Stop();
ul.lock();
SetFullMeasurementOutput(pedestal_output);
if (ImportPedestalG1G2(pedestal_output.receiver_output, 2, storage_cell))
state = JFJochState::Idle;
else
state = JFJochState::Inactive;
}
void JFJochStateMachine::Initialize() {
@@ -292,6 +344,8 @@ void JFJochStateMachine::Start(const DatasetSettings& settings) {
else
experiment.StorageCellStart(0);
experiment.IncrementSeriesID();
try {
state = JFJochState::Busy;
services.SetSpotFindingSettings(GetSpotFindingSettings());
@@ -321,7 +375,7 @@ c.wait(ul, [&] { return !IsRunning(); });
void JFJochStateMachine::MeasurementThread() {
try {
auto tmp_output = services.Stop(*calibration);
auto tmp_output = services.Stop();
SetFullMeasurementOutput(tmp_output);
{
std::unique_lock<std::mutex> ul(m);
@@ -377,15 +431,17 @@ void JFJochStateMachine::SetFullMeasurementOutput(const JFJochServicesOutput &ou
tmp.detector_width = experiment.GetXPixelsNum();
tmp.detector_height = experiment.GetYPixelsNum();
tmp.detector_pixel_depth = experiment.GetPixelDepth();
tmp.images_expected = experiment.GetImageNum();
tmp.compression_ratio = output.receiver_output.compressed_ratio;
tmp.compression_ratio = output.receiver_output.status.compressed_ratio;
tmp.collection_efficiency = output.receiver_output.efficiency;
tmp.images_collected = output.receiver_output.images_sent;
tmp.cancelled = output.receiver_output.cancelled;
tmp.max_image_number_sent = output.receiver_output.max_image_number_sent;
tmp.max_receive_delay = output.receiver_output.max_receive_delay;
tmp.indexing_rate = output.receiver_output.indexing_rate;
tmp.bkg_estimate = output.receiver_output.bkg_estimate;
tmp.images_collected = output.receiver_output.status.images_collected;
tmp.images_sent = output.receiver_output.status.images_sent;
tmp.cancelled = output.receiver_output.status.cancelled;
tmp.max_image_number_sent = output.receiver_output.status.max_image_number_sent;
tmp.max_receive_delay = output.receiver_output.status.max_receive_delay;
tmp.indexing_rate = output.receiver_output.status.indexing_rate;
tmp.bkg_estimate = output.receiver_output.status.bkg_estimate;
measurement_statistics = tmp;
}
@@ -398,6 +454,7 @@ void JFJochStateMachine::ClearAndSetMeasurementStatistics() {
tmp.detector_height = experiment.GetXPixelsNum();
tmp.detector_width = experiment.GetYPixelsNum();
tmp.detector_pixel_depth = experiment.GetPixelDepth();
tmp.images_expected = experiment.GetImageNum();
measurement_statistics = tmp;
}
@@ -407,8 +464,31 @@ void JFJochStateMachine::ClearMeasurementStatistics() {
}
std::optional<MeasurementStatistics> JFJochStateMachine::GetMeasurementStatistics() const {
std::unique_lock<std::mutex> ul(last_receiver_output_mutex);
return measurement_statistics;
auto rcv_status = services.GetReceiverStatus();
if (rcv_status) {
MeasurementStatistics tmp;
tmp.file_prefix = experiment.GetFilePrefix();
tmp.detector_width = experiment.GetXPixelsNum();
tmp.detector_height = experiment.GetYPixelsNum();
tmp.detector_pixel_depth = experiment.GetPixelDepth();
tmp.images_expected = experiment.GetImageNum();
tmp.compression_ratio = rcv_status->compressed_ratio;
tmp.collection_efficiency = -1.0;
tmp.images_collected = rcv_status->images_collected;
tmp.images_sent = rcv_status->images_sent;
tmp.cancelled = rcv_status->cancelled;
tmp.max_image_number_sent = rcv_status->max_image_number_sent;
tmp.max_receive_delay = rcv_status->max_receive_delay;
tmp.indexing_rate = rcv_status->indexing_rate;
tmp.bkg_estimate = rcv_status->bkg_estimate;
return tmp;
} else {
std::unique_lock<std::mutex> ul(last_receiver_output_mutex);
return measurement_statistics;
}
}
std::vector<JFCalibrationModuleStatistics> JFJochStateMachine::GetCalibrationStatistics() const {
@@ -434,6 +514,8 @@ DetectorSettings JFJochStateMachine::GetDetectorSettings() const {
ret.pedestal_g1_frames = experiment.GetPedestalG1Frames();
ret.pedestal_g2_frames = experiment.GetPedestalG2Frames();
ret.storage_cell_delay_ns = experiment.GetStorageCellDelay().count();
ret.fixed_gain_g1 = experiment.IsFixedGainG1();
ret.use_gain_hg0 = experiment.IsUsingGainHG0();
return ret;
}
@@ -468,7 +550,6 @@ BrokerStatus JFJochStateMachine::GetStatus() const {
if (rcv_status) {
ret.progress = rcv_status.value().progress;
ret.indexing_rate = rcv_status.value().indexing_rate;
ret.receiver_send_buffers_avail = rcv_status.value().send_buffers_avail;
}
} catch (JFJochException &e) {} // ignore exception in getting receiver status (don't really care, e.g. if receiver is down)
@@ -563,9 +644,9 @@ RadialIntegrationSettings JFJochStateMachine::GetRadialIntegrationSettings() con
ret.polarization_factor = experiment.GetPolarizationFactor();
ret.solid_angle_correction = experiment.GetApplySolidAngleCorr();
ret.q_spacing = experiment.GetQSpacingForRadialInt_recipA();
ret.low_q_recipA = experiment.GetLowQForRadialInt_recipA();
ret.high_q_recipA = experiment.GetHighQForRadialInt_recipA();
ret.q_spacing = experiment.GetQSpacingForAzimInt_recipA();
ret.low_q_recipA = experiment.GetLowQForAzimInt_recipA();
ret.high_q_recipA = experiment.GetHighQForAzimInt_recipA();
return ret;
}
+15 -4
View File
@@ -20,7 +20,6 @@ struct BrokerStatus {
JFJochState broker_state;
std::optional<float> progress;
std::optional<float> indexing_rate;
std::optional<float> receiver_send_buffers_avail;
};
struct DetectorListElement {
@@ -37,7 +36,9 @@ struct DetectorList {
struct MeasurementStatistics {
std::string file_prefix;
int64_t images_expected;
int64_t images_collected;
int64_t images_sent;
int64_t max_image_number_sent;
float collection_efficiency;
float compression_ratio;
@@ -78,6 +79,15 @@ struct DatasetSettings {
bool save_calibration;
std::optional<float> total_flux;
std::optional<float> attenuator_transmission;
std::optional<float> omega_step;
float omega_start;
Coord omega_axis;
std::string image_appendix;
std::string header_appendix;
std::optional<ROIRectangle> roi_sum_area;
};
struct DetectorSettings {
@@ -87,7 +97,8 @@ struct DetectorSettings {
int64_t storage_cell_count;
bool use_internal_packet_generator;
bool collect_raw_data;
bool use_gain_hg0;
bool fixed_gain_g1;
std::optional<int64_t> pedestal_g0_frames;
std::optional<int64_t> pedestal_g1_frames;
std::optional<int64_t> pedestal_g2_frames;
@@ -141,8 +152,8 @@ class JFJochStateMachine {
void MeasurementThread();
void PedestalThread(std::unique_lock<std::mutex> ul);
void InitializeThread(std::unique_lock<std::mutex> ul);
void ImportPedestal(const JFJochReceiverOutput &receiver_output, size_t gain_level, size_t storage_cell = 0);
void ImportPedestalG0(const JFJochReceiverOutput &receiver_output);
bool ImportPedestalG1G2(const JFJochReceiverOutput &receiver_output, size_t gain_level, size_t storage_cell = 0);
bool ImportPedestalG0(const JFJochReceiverOutput &receiver_output);
bool IsRunning() const; // Is state Busy/Pedestal/Measure
std::optional<std::string> CheckError();
+204 -21
View File
@@ -45,13 +45,18 @@ void DefaultApi::setupRoutes() {
Routes::Post(*router, base + "/deactivate", Routes::bind(&DefaultApi::deactivate_post_handler, this));
Routes::Post(*router, base + "/initialize", Routes::bind(&DefaultApi::initialize_post_handler, this));
Routes::Post(*router, base + "/pedestal", Routes::bind(&DefaultApi::pedestal_post_handler, this));
Routes::Get(*router, base + "/plot/adu_histogram", Routes::bind(&DefaultApi::plot_adu_histogram_get_handler, this));
Routes::Post(*router, base + "/plot/bkg_estimate", Routes::bind(&DefaultApi::plot_bkg_estimate_post_handler, this));
Routes::Post(*router, base + "/plot/error_pixel", Routes::bind(&DefaultApi::plot_error_pixel_post_handler, this));
Routes::Post(*router, base + "/plot/image_collection_efficiency", Routes::bind(&DefaultApi::plot_image_collection_efficiency_post_handler, this));
Routes::Get(*router, base + "/plot/indexing_rate_per_file", Routes::bind(&DefaultApi::plot_indexing_rate_per_file_get_handler, this));
Routes::Post(*router, base + "/plot/indexing_rate", Routes::bind(&DefaultApi::plot_indexing_rate_post_handler, this));
Routes::Get(*router, base + "/plot/rad_int", Routes::bind(&DefaultApi::plot_rad_int_get_handler, this));
Routes::Get(*router, base + "/plot/rad_int_per_file", Routes::bind(&DefaultApi::plot_rad_int_per_file_get_handler, this));
Routes::Post(*router, base + "/plot/receiver_delay", Routes::bind(&DefaultApi::plot_receiver_delay_post_handler, this));
Routes::Post(*router, base + "/plot/roi_sum", Routes::bind(&DefaultApi::plot_roi_sum_post_handler, this));
Routes::Post(*router, base + "/plot/saturated_pixel", Routes::bind(&DefaultApi::plot_saturated_pixel_post_handler, this));
Routes::Post(*router, base + "/plot/spot_count", Routes::bind(&DefaultApi::plot_spot_count_post_handler, this));
Routes::Post(*router, base + "/plot/strong_pixel", Routes::bind(&DefaultApi::plot_strong_pixel_post_handler, this));
Routes::Post(*router, base + "/start", Routes::bind(&DefaultApi::start_post_handler, this));
Routes::Get(*router, base + "/statistics/calibration", Routes::bind(&DefaultApi::statistics_calibration_get_handler, this));
Routes::Get(*router, base + "/statistics/data_collection", Routes::bind(&DefaultApi::statistics_data_collection_get_handler, this));
@@ -372,26 +377,6 @@ void DefaultApi::pedestal_post_handler(const Pistache::Rest::Request &, Pistache
response.send(Pistache::Http::Code::Internal_Server_Error, e.what());
}
}
void DefaultApi::plot_adu_histogram_get_handler(const Pistache::Rest::Request &, Pistache::Http::ResponseWriter response) {
try {
try {
this->plot_adu_histogram_get(response);
} catch (Pistache::Http::HttpError &e) {
response.send(static_cast<Pistache::Http::Code>(e.code()), e.what());
return;
} catch (std::exception &e) {
const std::pair<Pistache::Http::Code, std::string> errorInfo = this->handleOperationException(e);
response.send(errorInfo.first, errorInfo.second);
return;
}
} catch (std::exception &e) {
response.send(Pistache::Http::Code::Internal_Server_Error, e.what());
}
}
void DefaultApi::plot_bkg_estimate_post_handler(const Pistache::Rest::Request &request, Pistache::Http::ResponseWriter response) {
try {
@@ -425,6 +410,72 @@ void DefaultApi::plot_bkg_estimate_post_handler(const Pistache::Rest::Request &r
response.send(Pistache::Http::Code::Internal_Server_Error, e.what());
}
}
void DefaultApi::plot_error_pixel_post_handler(const Pistache::Rest::Request &request, Pistache::Http::ResponseWriter response) {
try {
// Getting the body param
Plot_request plotRequest;
try {
nlohmann::json::parse(request.body()).get_to(plotRequest);
plotRequest.validate();
} catch (std::exception &e) {
const std::pair<Pistache::Http::Code, std::string> errorInfo = this->handleParsingException(e);
response.send(errorInfo.first, errorInfo.second);
return;
}
try {
this->plot_error_pixel_post(plotRequest, response);
} catch (Pistache::Http::HttpError &e) {
response.send(static_cast<Pistache::Http::Code>(e.code()), e.what());
return;
} catch (std::exception &e) {
const std::pair<Pistache::Http::Code, std::string> errorInfo = this->handleOperationException(e);
response.send(errorInfo.first, errorInfo.second);
return;
}
} catch (std::exception &e) {
response.send(Pistache::Http::Code::Internal_Server_Error, e.what());
}
}
void DefaultApi::plot_image_collection_efficiency_post_handler(const Pistache::Rest::Request &request, Pistache::Http::ResponseWriter response) {
try {
// Getting the body param
Plot_request plotRequest;
try {
nlohmann::json::parse(request.body()).get_to(plotRequest);
plotRequest.validate();
} catch (std::exception &e) {
const std::pair<Pistache::Http::Code, std::string> errorInfo = this->handleParsingException(e);
response.send(errorInfo.first, errorInfo.second);
return;
}
try {
this->plot_image_collection_efficiency_post(plotRequest, response);
} catch (Pistache::Http::HttpError &e) {
response.send(static_cast<Pistache::Http::Code>(e.code()), e.what());
return;
} catch (std::exception &e) {
const std::pair<Pistache::Http::Code, std::string> errorInfo = this->handleOperationException(e);
response.send(errorInfo.first, errorInfo.second);
return;
}
} catch (std::exception &e) {
response.send(Pistache::Http::Code::Internal_Server_Error, e.what());
}
}
void DefaultApi::plot_indexing_rate_per_file_get_handler(const Pistache::Rest::Request &, Pistache::Http::ResponseWriter response) {
try {
@@ -518,6 +569,105 @@ void DefaultApi::plot_rad_int_per_file_get_handler(const Pistache::Rest::Request
response.send(Pistache::Http::Code::Internal_Server_Error, e.what());
}
}
void DefaultApi::plot_receiver_delay_post_handler(const Pistache::Rest::Request &request, Pistache::Http::ResponseWriter response) {
try {
// Getting the body param
Plot_request plotRequest;
try {
nlohmann::json::parse(request.body()).get_to(plotRequest);
plotRequest.validate();
} catch (std::exception &e) {
const std::pair<Pistache::Http::Code, std::string> errorInfo = this->handleParsingException(e);
response.send(errorInfo.first, errorInfo.second);
return;
}
try {
this->plot_receiver_delay_post(plotRequest, response);
} catch (Pistache::Http::HttpError &e) {
response.send(static_cast<Pistache::Http::Code>(e.code()), e.what());
return;
} catch (std::exception &e) {
const std::pair<Pistache::Http::Code, std::string> errorInfo = this->handleOperationException(e);
response.send(errorInfo.first, errorInfo.second);
return;
}
} catch (std::exception &e) {
response.send(Pistache::Http::Code::Internal_Server_Error, e.what());
}
}
void DefaultApi::plot_roi_sum_post_handler(const Pistache::Rest::Request &request, Pistache::Http::ResponseWriter response) {
try {
// Getting the body param
Plot_request plotRequest;
try {
nlohmann::json::parse(request.body()).get_to(plotRequest);
plotRequest.validate();
} catch (std::exception &e) {
const std::pair<Pistache::Http::Code, std::string> errorInfo = this->handleParsingException(e);
response.send(errorInfo.first, errorInfo.second);
return;
}
try {
this->plot_roi_sum_post(plotRequest, response);
} catch (Pistache::Http::HttpError &e) {
response.send(static_cast<Pistache::Http::Code>(e.code()), e.what());
return;
} catch (std::exception &e) {
const std::pair<Pistache::Http::Code, std::string> errorInfo = this->handleOperationException(e);
response.send(errorInfo.first, errorInfo.second);
return;
}
} catch (std::exception &e) {
response.send(Pistache::Http::Code::Internal_Server_Error, e.what());
}
}
void DefaultApi::plot_saturated_pixel_post_handler(const Pistache::Rest::Request &request, Pistache::Http::ResponseWriter response) {
try {
// Getting the body param
Plot_request plotRequest;
try {
nlohmann::json::parse(request.body()).get_to(plotRequest);
plotRequest.validate();
} catch (std::exception &e) {
const std::pair<Pistache::Http::Code, std::string> errorInfo = this->handleParsingException(e);
response.send(errorInfo.first, errorInfo.second);
return;
}
try {
this->plot_saturated_pixel_post(plotRequest, response);
} catch (Pistache::Http::HttpError &e) {
response.send(static_cast<Pistache::Http::Code>(e.code()), e.what());
return;
} catch (std::exception &e) {
const std::pair<Pistache::Http::Code, std::string> errorInfo = this->handleOperationException(e);
response.send(errorInfo.first, errorInfo.second);
return;
}
} catch (std::exception &e) {
response.send(Pistache::Http::Code::Internal_Server_Error, e.what());
}
}
void DefaultApi::plot_spot_count_post_handler(const Pistache::Rest::Request &request, Pistache::Http::ResponseWriter response) {
try {
@@ -551,6 +701,39 @@ void DefaultApi::plot_spot_count_post_handler(const Pistache::Rest::Request &req
response.send(Pistache::Http::Code::Internal_Server_Error, e.what());
}
}
void DefaultApi::plot_strong_pixel_post_handler(const Pistache::Rest::Request &request, Pistache::Http::ResponseWriter response) {
try {
// Getting the body param
Plot_request plotRequest;
try {
nlohmann::json::parse(request.body()).get_to(plotRequest);
plotRequest.validate();
} catch (std::exception &e) {
const std::pair<Pistache::Http::Code, std::string> errorInfo = this->handleParsingException(e);
response.send(errorInfo.first, errorInfo.second);
return;
}
try {
this->plot_strong_pixel_post(plotRequest, response);
} catch (Pistache::Http::HttpError &e) {
response.send(static_cast<Pistache::Http::Code>(e.code()), e.what());
return;
} catch (std::exception &e) {
const std::pair<Pistache::Http::Code, std::string> errorInfo = this->handleOperationException(e);
response.send(errorInfo.first, errorInfo.second);
return;
}
} catch (std::exception &e) {
response.send(Pistache::Http::Code::Internal_Server_Error, e.what());
}
}
void DefaultApi::start_post_handler(const Pistache::Rest::Request &request, Pistache::Http::ResponseWriter response) {
try {
+54 -8
View File
@@ -67,13 +67,18 @@ private:
void deactivate_post_handler(const Pistache::Rest::Request &request, Pistache::Http::ResponseWriter response);
void initialize_post_handler(const Pistache::Rest::Request &request, Pistache::Http::ResponseWriter response);
void pedestal_post_handler(const Pistache::Rest::Request &request, Pistache::Http::ResponseWriter response);
void plot_adu_histogram_get_handler(const Pistache::Rest::Request &request, Pistache::Http::ResponseWriter response);
void plot_bkg_estimate_post_handler(const Pistache::Rest::Request &request, Pistache::Http::ResponseWriter response);
void plot_error_pixel_post_handler(const Pistache::Rest::Request &request, Pistache::Http::ResponseWriter response);
void plot_image_collection_efficiency_post_handler(const Pistache::Rest::Request &request, Pistache::Http::ResponseWriter response);
void plot_indexing_rate_per_file_get_handler(const Pistache::Rest::Request &request, Pistache::Http::ResponseWriter response);
void plot_indexing_rate_post_handler(const Pistache::Rest::Request &request, Pistache::Http::ResponseWriter response);
void plot_rad_int_get_handler(const Pistache::Rest::Request &request, Pistache::Http::ResponseWriter response);
void plot_rad_int_per_file_get_handler(const Pistache::Rest::Request &request, Pistache::Http::ResponseWriter response);
void plot_receiver_delay_post_handler(const Pistache::Rest::Request &request, Pistache::Http::ResponseWriter response);
void plot_roi_sum_post_handler(const Pistache::Rest::Request &request, Pistache::Http::ResponseWriter response);
void plot_saturated_pixel_post_handler(const Pistache::Rest::Request &request, Pistache::Http::ResponseWriter response);
void plot_spot_count_post_handler(const Pistache::Rest::Request &request, Pistache::Http::ResponseWriter response);
void plot_strong_pixel_post_handler(const Pistache::Rest::Request &request, Pistache::Http::ResponseWriter response);
void start_post_handler(const Pistache::Rest::Request &request, Pistache::Http::ResponseWriter response);
void statistics_calibration_get_handler(const Pistache::Rest::Request &request, Pistache::Http::ResponseWriter response);
void statistics_data_collection_get_handler(const Pistache::Rest::Request &request, Pistache::Http::ResponseWriter response);
@@ -187,13 +192,6 @@ private:
/// </remarks>
virtual void pedestal_post(Pistache::Http::ResponseWriter &response) = 0;
/// <summary>
/// Generate ADU histogram
/// </summary>
/// <remarks>
/// ADU histogram for all images within current data collection
/// </remarks>
virtual void plot_adu_histogram_get(Pistache::Http::ResponseWriter &response) = 0;
/// <summary>
/// Generate background estimate plot
/// </summary>
/// <remarks>
@@ -202,6 +200,22 @@ private:
/// <param name="plotRequest"> (optional)</param>
virtual void plot_bkg_estimate_post(const org::openapitools::server::model::Plot_request &plotRequest, Pistache::Http::ResponseWriter &response) = 0;
/// <summary>
/// Generate error pixels plot
/// </summary>
/// <remarks>
/// Count of error pixels per image; binning is configurable
/// </remarks>
/// <param name="plotRequest"> (optional)</param>
virtual void plot_error_pixel_post(const org::openapitools::server::model::Plot_request &plotRequest, Pistache::Http::ResponseWriter &response) = 0;
/// <summary>
/// Generate image collection efficiency plot
/// </summary>
/// <remarks>
/// Ratio of collected and expected packets per image; binning is configurable
/// </remarks>
/// <param name="plotRequest"> (optional)</param>
virtual void plot_image_collection_efficiency_post(const org::openapitools::server::model::Plot_request &plotRequest, Pistache::Http::ResponseWriter &response) = 0;
/// <summary>
/// Generate indexing rate per file
/// </summary>
/// <remarks>
@@ -231,6 +245,30 @@ private:
/// </remarks>
virtual void plot_rad_int_per_file_get(Pistache::Http::ResponseWriter &response) = 0;
/// <summary>
/// Generate receiver delay plot
/// </summary>
/// <remarks>
/// Amount of frames the receiver is behind the FPGA for each image - used for internal debugging; binning is configurable
/// </remarks>
/// <param name="plotRequest"> (optional)</param>
virtual void plot_receiver_delay_post(const org::openapitools::server::model::Plot_request &plotRequest, Pistache::Http::ResponseWriter &response) = 0;
/// <summary>
/// Generate ROI sum plot
/// </summary>
/// <remarks>
/// Sum of ROI rectangle per image; binning is configurable
/// </remarks>
/// <param name="plotRequest"> (optional)</param>
virtual void plot_roi_sum_post(const org::openapitools::server::model::Plot_request &plotRequest, Pistache::Http::ResponseWriter &response) = 0;
/// <summary>
/// Generate saturated pixels plot
/// </summary>
/// <remarks>
/// Count of saturated pixels per image; binning is configurable
/// </remarks>
/// <param name="plotRequest"> (optional)</param>
virtual void plot_saturated_pixel_post(const org::openapitools::server::model::Plot_request &plotRequest, Pistache::Http::ResponseWriter &response) = 0;
/// <summary>
/// Generate spot count plot
/// </summary>
/// <remarks>
@@ -239,6 +277,14 @@ private:
/// <param name="plotRequest"> (optional)</param>
virtual void plot_spot_count_post(const org::openapitools::server::model::Plot_request &plotRequest, Pistache::Http::ResponseWriter &response) = 0;
/// <summary>
/// Generate strong pixels plot
/// </summary>
/// <remarks>
/// Count of strong pixels per image (from spot finding); binning is configurable
/// </remarks>
/// <param name="plotRequest"> (optional)</param>
virtual void plot_strong_pixel_post(const org::openapitools::server::model::Plot_request &plotRequest, Pistache::Http::ResponseWriter &response) = 0;
/// <summary>
/// Start detector
/// </summary>
/// <remarks>
+1 -49
View File
@@ -26,8 +26,6 @@ Broker_status::Broker_status()
m_ProgressIsSet = false;
m_Indexing_rate = 0.0f;
m_Indexing_rateIsSet = false;
m_Receiver_send_buffers_avail = 0.0f;
m_Receiver_send_buffers_availIsSet = false;
}
@@ -76,25 +74,6 @@ bool Broker_status::validate(std::stringstream& msg, const std::string& pathPref
const std::string currentValuePath = _pathPrefix + ".indexingRate";
if (value < static_cast<float>(0.0))
{
success = false;
msg << currentValuePath << ": must be greater than or equal to 0.0;";
}
if (value > static_cast<float>(1.0))
{
success = false;
msg << currentValuePath << ": must be less than or equal to 1.0;";
}
}
if (receiverSendBuffersAvailIsSet())
{
const float& value = m_Receiver_send_buffers_avail;
const std::string currentValuePath = _pathPrefix + ".receiverSendBuffersAvail";
if (value < static_cast<float>(0.0))
{
success = false;
@@ -123,10 +102,7 @@ bool Broker_status::operator==(const Broker_status& rhs) const
((!progressIsSet() && !rhs.progressIsSet()) || (progressIsSet() && rhs.progressIsSet() && getProgress() == rhs.getProgress())) &&
((!indexingRateIsSet() && !rhs.indexingRateIsSet()) || (indexingRateIsSet() && rhs.indexingRateIsSet() && getIndexingRate() == rhs.getIndexingRate())) &&
((!receiverSendBuffersAvailIsSet() && !rhs.receiverSendBuffersAvailIsSet()) || (receiverSendBuffersAvailIsSet() && rhs.receiverSendBuffersAvailIsSet() && getReceiverSendBuffersAvail() == rhs.getReceiverSendBuffersAvail()))
((!indexingRateIsSet() && !rhs.indexingRateIsSet()) || (indexingRateIsSet() && rhs.indexingRateIsSet() && getIndexingRate() == rhs.getIndexingRate()))
;
}
@@ -144,8 +120,6 @@ void to_json(nlohmann::json& j, const Broker_status& o)
j["progress"] = o.m_Progress;
if(o.indexingRateIsSet())
j["indexing_rate"] = o.m_Indexing_rate;
if(o.receiverSendBuffersAvailIsSet())
j["receiver_send_buffers_avail"] = o.m_Receiver_send_buffers_avail;
}
@@ -162,11 +136,6 @@ void from_json(const nlohmann::json& j, Broker_status& o)
j.at("indexing_rate").get_to(o.m_Indexing_rate);
o.m_Indexing_rateIsSet = true;
}
if(j.find("receiver_send_buffers_avail") != j.end())
{
j.at("receiver_send_buffers_avail").get_to(o.m_Receiver_send_buffers_avail);
o.m_Receiver_send_buffers_availIsSet = true;
}
}
@@ -212,23 +181,6 @@ void Broker_status::unsetIndexing_rate()
{
m_Indexing_rateIsSet = false;
}
float Broker_status::getReceiverSendBuffersAvail() const
{
return m_Receiver_send_buffers_avail;
}
void Broker_status::setReceiverSendBuffersAvail(float const value)
{
m_Receiver_send_buffers_avail = value;
m_Receiver_send_buffers_availIsSet = true;
}
bool Broker_status::receiverSendBuffersAvailIsSet() const
{
return m_Receiver_send_buffers_availIsSet;
}
void Broker_status::unsetReceiver_send_buffers_avail()
{
m_Receiver_send_buffers_availIsSet = false;
}
} // namespace org::openapitools::server::model
-9
View File
@@ -77,13 +77,6 @@ public:
void setIndexingRate(float const value);
bool indexingRateIsSet() const;
void unsetIndexing_rate();
/// <summary>
///
/// </summary>
float getReceiverSendBuffersAvail() const;
void setReceiverSendBuffersAvail(float const value);
bool receiverSendBuffersAvailIsSet() const;
void unsetReceiver_send_buffers_avail();
friend void to_json(nlohmann::json& j, const Broker_status& o);
friend void from_json(const nlohmann::json& j, Broker_status& o);
@@ -94,8 +87,6 @@ protected:
bool m_ProgressIsSet;
float m_Indexing_rate;
bool m_Indexing_rateIsSet;
float m_Receiver_send_buffers_avail;
bool m_Receiver_send_buffers_availIsSet;
};
+115 -1
View File
@@ -47,6 +47,12 @@ Dataset_settings::Dataset_settings()
m_Total_fluxIsSet = false;
m_Transmission = 0.0f;
m_TransmissionIsSet = false;
m_OmegaIsSet = false;
m_Header_appendix = "";
m_Header_appendixIsSet = false;
m_Image_appendix = "";
m_Image_appendixIsSet = false;
m_Roi_sum_areaIsSet = false;
m_Unit_cellIsSet = false;
}
@@ -197,7 +203,7 @@ bool Dataset_settings::validate(std::stringstream& msg, const std::string& pathP
}
}
return success;
}
@@ -255,6 +261,18 @@ bool Dataset_settings::operator==(const Dataset_settings& rhs) const
((!transmissionIsSet() && !rhs.transmissionIsSet()) || (transmissionIsSet() && rhs.transmissionIsSet() && getTransmission() == rhs.getTransmission())) &&
((!omegaIsSet() && !rhs.omegaIsSet()) || (omegaIsSet() && rhs.omegaIsSet() && getOmega() == rhs.getOmega())) &&
((!headerAppendixIsSet() && !rhs.headerAppendixIsSet()) || (headerAppendixIsSet() && rhs.headerAppendixIsSet() && getHeaderAppendix() == rhs.getHeaderAppendix())) &&
((!imageAppendixIsSet() && !rhs.imageAppendixIsSet()) || (imageAppendixIsSet() && rhs.imageAppendixIsSet() && getImageAppendix() == rhs.getImageAppendix())) &&
((!roiSumAreaIsSet() && !rhs.roiSumAreaIsSet()) || (roiSumAreaIsSet() && rhs.roiSumAreaIsSet() && getRoiSumArea() == rhs.getRoiSumArea())) &&
((!unitCellIsSet() && !rhs.unitCellIsSet()) || (unitCellIsSet() && rhs.unitCellIsSet() && getUnitCell() == rhs.getUnitCell()))
;
@@ -294,6 +312,14 @@ void to_json(nlohmann::json& j, const Dataset_settings& o)
j["total_flux"] = o.m_Total_flux;
if(o.transmissionIsSet())
j["transmission"] = o.m_Transmission;
if(o.omegaIsSet())
j["omega"] = o.m_Omega;
if(o.headerAppendixIsSet())
j["header_appendix"] = o.m_Header_appendix;
if(o.imageAppendixIsSet())
j["image_appendix"] = o.m_Image_appendix;
if(o.roiSumAreaIsSet())
j["roi_sum_area"] = o.m_Roi_sum_area;
if(o.unitCellIsSet())
j["unit_cell"] = o.m_Unit_cell;
@@ -357,6 +383,26 @@ void from_json(const nlohmann::json& j, Dataset_settings& o)
j.at("transmission").get_to(o.m_Transmission);
o.m_TransmissionIsSet = true;
}
if(j.find("omega") != j.end())
{
j.at("omega").get_to(o.m_Omega);
o.m_OmegaIsSet = true;
}
if(j.find("header_appendix") != j.end())
{
j.at("header_appendix").get_to(o.m_Header_appendix);
o.m_Header_appendixIsSet = true;
}
if(j.find("image_appendix") != j.end())
{
j.at("image_appendix").get_to(o.m_Image_appendix);
o.m_Image_appendixIsSet = true;
}
if(j.find("roi_sum_area") != j.end())
{
j.at("roi_sum_area").get_to(o.m_Roi_sum_area);
o.m_Roi_sum_areaIsSet = true;
}
if(j.find("unit_cell") != j.end())
{
j.at("unit_cell").get_to(o.m_Unit_cell);
@@ -583,6 +629,74 @@ void Dataset_settings::unsetTransmission()
{
m_TransmissionIsSet = false;
}
org::openapitools::server::model::Rotation_axis Dataset_settings::getOmega() const
{
return m_Omega;
}
void Dataset_settings::setOmega(org::openapitools::server::model::Rotation_axis const& value)
{
m_Omega = value;
m_OmegaIsSet = true;
}
bool Dataset_settings::omegaIsSet() const
{
return m_OmegaIsSet;
}
void Dataset_settings::unsetOmega()
{
m_OmegaIsSet = false;
}
std::string Dataset_settings::getHeaderAppendix() const
{
return m_Header_appendix;
}
void Dataset_settings::setHeaderAppendix(std::string const& value)
{
m_Header_appendix = value;
m_Header_appendixIsSet = true;
}
bool Dataset_settings::headerAppendixIsSet() const
{
return m_Header_appendixIsSet;
}
void Dataset_settings::unsetHeader_appendix()
{
m_Header_appendixIsSet = false;
}
std::string Dataset_settings::getImageAppendix() const
{
return m_Image_appendix;
}
void Dataset_settings::setImageAppendix(std::string const& value)
{
m_Image_appendix = value;
m_Image_appendixIsSet = true;
}
bool Dataset_settings::imageAppendixIsSet() const
{
return m_Image_appendixIsSet;
}
void Dataset_settings::unsetImage_appendix()
{
m_Image_appendixIsSet = false;
}
org::openapitools::server::model::Dataset_settings_roi_sum_area Dataset_settings::getRoiSumArea() const
{
return m_Roi_sum_area;
}
void Dataset_settings::setRoiSumArea(org::openapitools::server::model::Dataset_settings_roi_sum_area const& value)
{
m_Roi_sum_area = value;
m_Roi_sum_areaIsSet = true;
}
bool Dataset_settings::roiSumAreaIsSet() const
{
return m_Roi_sum_areaIsSet;
}
void Dataset_settings::unsetRoi_sum_area()
{
m_Roi_sum_areaIsSet = false;
}
org::openapitools::server::model::Dataset_settings_unit_cell Dataset_settings::getUnitCell() const
{
return m_Unit_cell;
+38
View File
@@ -19,7 +19,9 @@
#define Dataset_settings_H_
#include "Rotation_axis.h"
#include <string>
#include "Dataset_settings_roi_sum_area.h"
#include "Dataset_settings_unit_cell.h"
#include <nlohmann/json.hpp>
@@ -162,6 +164,34 @@ public:
/// <summary>
///
/// </summary>
org::openapitools::server::model::Rotation_axis getOmega() const;
void setOmega(org::openapitools::server::model::Rotation_axis const& value);
bool omegaIsSet() const;
void unsetOmega();
/// <summary>
/// Header appendix, added as user_data to start message
/// </summary>
std::string getHeaderAppendix() const;
void setHeaderAppendix(std::string const& value);
bool headerAppendixIsSet() const;
void unsetHeader_appendix();
/// <summary>
/// Image appendix, added as user_data to image message
/// </summary>
std::string getImageAppendix() const;
void setImageAppendix(std::string const& value);
bool imageAppendixIsSet() const;
void unsetImage_appendix();
/// <summary>
///
/// </summary>
org::openapitools::server::model::Dataset_settings_roi_sum_area getRoiSumArea() const;
void setRoiSumArea(org::openapitools::server::model::Dataset_settings_roi_sum_area const& value);
bool roiSumAreaIsSet() const;
void unsetRoi_sum_area();
/// <summary>
///
/// </summary>
org::openapitools::server::model::Dataset_settings_unit_cell getUnitCell() const;
void setUnitCell(org::openapitools::server::model::Dataset_settings_unit_cell const& value);
bool unitCellIsSet() const;
@@ -202,6 +232,14 @@ protected:
bool m_Total_fluxIsSet;
float m_Transmission;
bool m_TransmissionIsSet;
org::openapitools::server::model::Rotation_axis m_Omega;
bool m_OmegaIsSet;
std::string m_Header_appendix;
bool m_Header_appendixIsSet;
std::string m_Image_appendix;
bool m_Image_appendixIsSet;
org::openapitools::server::model::Dataset_settings_roi_sum_area m_Roi_sum_area;
bool m_Roi_sum_areaIsSet;
org::openapitools::server::model::Dataset_settings_unit_cell m_Unit_cell;
bool m_Unit_cellIsSet;
@@ -0,0 +1,133 @@
/**
* Jungfraujoch
* Jungfraujoch Broker Web API
*
* The version of the OpenAPI document: 1.0.0
*
*
* NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech).
* https://openapi-generator.tech
* Do not edit the class manually.
*/
#include "Dataset_settings_roi_sum_area.h"
#include "Helpers.h"
#include <sstream>
namespace org::openapitools::server::model
{
Dataset_settings_roi_sum_area::Dataset_settings_roi_sum_area()
{
m_X_min = 0L;
m_X_max = 0L;
m_Y_min = 0L;
m_Y_max = 0L;
}
void Dataset_settings_roi_sum_area::validate() const
{
std::stringstream msg;
if (!validate(msg))
{
throw org::openapitools::server::helpers::ValidationException(msg.str());
}
}
bool Dataset_settings_roi_sum_area::validate(std::stringstream& msg) const
{
return validate(msg, "");
}
bool Dataset_settings_roi_sum_area::validate(std::stringstream& msg, const std::string& pathPrefix) const
{
bool success = true;
const std::string _pathPrefix = pathPrefix.empty() ? "Dataset_settings_roi_sum_area" : pathPrefix;
return success;
}
bool Dataset_settings_roi_sum_area::operator==(const Dataset_settings_roi_sum_area& rhs) const
{
return
(getXMin() == rhs.getXMin())
&&
(getXMax() == rhs.getXMax())
&&
(getYMin() == rhs.getYMin())
&&
(getYMax() == rhs.getYMax())
;
}
bool Dataset_settings_roi_sum_area::operator!=(const Dataset_settings_roi_sum_area& rhs) const
{
return !(*this == rhs);
}
void to_json(nlohmann::json& j, const Dataset_settings_roi_sum_area& o)
{
j = nlohmann::json();
j["x_min"] = o.m_X_min;
j["x_max"] = o.m_X_max;
j["y_min"] = o.m_Y_min;
j["y_max"] = o.m_Y_max;
}
void from_json(const nlohmann::json& j, Dataset_settings_roi_sum_area& o)
{
j.at("x_min").get_to(o.m_X_min);
j.at("x_max").get_to(o.m_X_max);
j.at("y_min").get_to(o.m_Y_min);
j.at("y_max").get_to(o.m_Y_max);
}
int64_t Dataset_settings_roi_sum_area::getXMin() const
{
return m_X_min;
}
void Dataset_settings_roi_sum_area::setXMin(int64_t const value)
{
m_X_min = value;
}
int64_t Dataset_settings_roi_sum_area::getXMax() const
{
return m_X_max;
}
void Dataset_settings_roi_sum_area::setXMax(int64_t const value)
{
m_X_max = value;
}
int64_t Dataset_settings_roi_sum_area::getYMin() const
{
return m_Y_min;
}
void Dataset_settings_roi_sum_area::setYMin(int64_t const value)
{
m_Y_min = value;
}
int64_t Dataset_settings_roi_sum_area::getYMax() const
{
return m_Y_max;
}
void Dataset_settings_roi_sum_area::setYMax(int64_t const value)
{
m_Y_max = value;
}
} // namespace org::openapitools::server::model
@@ -0,0 +1,97 @@
/**
* Jungfraujoch
* Jungfraujoch Broker Web API
*
* The version of the OpenAPI document: 1.0.0
*
*
* NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech).
* https://openapi-generator.tech
* Do not edit the class manually.
*/
/*
* Dataset_settings_roi_sum_area.h
*
* Rectangle for ROI summation
*/
#ifndef Dataset_settings_roi_sum_area_H_
#define Dataset_settings_roi_sum_area_H_
#include <nlohmann/json.hpp>
namespace org::openapitools::server::model
{
/// <summary>
/// Rectangle for ROI summation
/// </summary>
class Dataset_settings_roi_sum_area
{
public:
Dataset_settings_roi_sum_area();
virtual ~Dataset_settings_roi_sum_area() = default;
/// <summary>
/// Validate the current data in the model. Throws a ValidationException on failure.
/// </summary>
void validate() const;
/// <summary>
/// Validate the current data in the model. Returns false on error and writes an error
/// message into the given stringstream.
/// </summary>
bool validate(std::stringstream& msg) const;
/// <summary>
/// Helper overload for validate. Used when one model stores another model and calls it's validate.
/// Not meant to be called outside that case.
/// </summary>
bool validate(std::stringstream& msg, const std::string& pathPrefix) const;
bool operator==(const Dataset_settings_roi_sum_area& rhs) const;
bool operator!=(const Dataset_settings_roi_sum_area& rhs) const;
/////////////////////////////////////////////
/// Dataset_settings_roi_sum_area members
/// <summary>
///
/// </summary>
int64_t getXMin() const;
void setXMin(int64_t const value);
/// <summary>
///
/// </summary>
int64_t getXMax() const;
void setXMax(int64_t const value);
/// <summary>
///
/// </summary>
int64_t getYMin() const;
void setYMin(int64_t const value);
/// <summary>
///
/// </summary>
int64_t getYMax() const;
void setYMax(int64_t const value);
friend void to_json(nlohmann::json& j, const Dataset_settings_roi_sum_area& o);
friend void from_json(const nlohmann::json& j, Dataset_settings_roi_sum_area& o);
protected:
int64_t m_X_min;
int64_t m_X_max;
int64_t m_Y_min;
int64_t m_Y_max;
};
} // namespace org::openapitools::server::model
#endif /* Dataset_settings_roi_sum_area_H_ */
+60 -2
View File
@@ -38,6 +38,10 @@ Detector_settings::Detector_settings()
m_Pedestal_g2_framesIsSet = false;
m_Storage_cell_delay_ns = 0L;
m_Storage_cell_delay_nsIsSet = false;
m_Fixed_gain_g1 = false;
m_Fixed_gain_g1IsSet = false;
m_Use_gain_hg0 = false;
m_Use_gain_hg0IsSet = false;
}
@@ -135,7 +139,7 @@ bool Detector_settings::validate(std::stringstream& msg, const std::string& path
}
}
return success;
}
@@ -169,7 +173,13 @@ bool Detector_settings::operator==(const Detector_settings& rhs) const
((!pedestalG2FramesIsSet() && !rhs.pedestalG2FramesIsSet()) || (pedestalG2FramesIsSet() && rhs.pedestalG2FramesIsSet() && getPedestalG2Frames() == rhs.getPedestalG2Frames())) &&
((!storageCellDelayNsIsSet() && !rhs.storageCellDelayNsIsSet()) || (storageCellDelayNsIsSet() && rhs.storageCellDelayNsIsSet() && getStorageCellDelayNs() == rhs.getStorageCellDelayNs()))
((!storageCellDelayNsIsSet() && !rhs.storageCellDelayNsIsSet()) || (storageCellDelayNsIsSet() && rhs.storageCellDelayNsIsSet() && getStorageCellDelayNs() == rhs.getStorageCellDelayNs())) &&
((!fixedGainG1IsSet() && !rhs.fixedGainG1IsSet()) || (fixedGainG1IsSet() && rhs.fixedGainG1IsSet() && isFixedGainG1() == rhs.isFixedGainG1())) &&
((!useGainHg0IsSet() && !rhs.useGainHg0IsSet()) || (useGainHg0IsSet() && rhs.useGainHg0IsSet() && isUseGainHg0() == rhs.isUseGainHg0()))
;
}
@@ -199,6 +209,10 @@ void to_json(nlohmann::json& j, const Detector_settings& o)
j["pedestal_g2_frames"] = o.m_Pedestal_g2_frames;
if(o.storageCellDelayNsIsSet())
j["storage_cell_delay_ns"] = o.m_Storage_cell_delay_ns;
if(o.fixedGainG1IsSet())
j["fixed_gain_g1"] = o.m_Fixed_gain_g1;
if(o.useGainHg0IsSet())
j["use_gain_hg0"] = o.m_Use_gain_hg0;
}
@@ -245,6 +259,16 @@ void from_json(const nlohmann::json& j, Detector_settings& o)
j.at("storage_cell_delay_ns").get_to(o.m_Storage_cell_delay_ns);
o.m_Storage_cell_delay_nsIsSet = true;
}
if(j.find("fixed_gain_g1") != j.end())
{
j.at("fixed_gain_g1").get_to(o.m_Fixed_gain_g1);
o.m_Fixed_gain_g1IsSet = true;
}
if(j.find("use_gain_hg0") != j.end())
{
j.at("use_gain_hg0").get_to(o.m_Use_gain_hg0);
o.m_Use_gain_hg0IsSet = true;
}
}
@@ -392,6 +416,40 @@ void Detector_settings::unsetStorage_cell_delay_ns()
{
m_Storage_cell_delay_nsIsSet = false;
}
bool Detector_settings::isFixedGainG1() const
{
return m_Fixed_gain_g1;
}
void Detector_settings::setFixedGainG1(bool const value)
{
m_Fixed_gain_g1 = value;
m_Fixed_gain_g1IsSet = true;
}
bool Detector_settings::fixedGainG1IsSet() const
{
return m_Fixed_gain_g1IsSet;
}
void Detector_settings::unsetFixed_gain_g1()
{
m_Fixed_gain_g1IsSet = false;
}
bool Detector_settings::isUseGainHg0() const
{
return m_Use_gain_hg0;
}
void Detector_settings::setUseGainHg0(bool const value)
{
m_Use_gain_hg0 = value;
m_Use_gain_hg0IsSet = true;
}
bool Detector_settings::useGainHg0IsSet() const
{
return m_Use_gain_hg0IsSet;
}
void Detector_settings::unsetUse_gain_hg0()
{
m_Use_gain_hg0IsSet = false;
}
} // namespace org::openapitools::server::model
+21 -3
View File
@@ -77,14 +77,14 @@ public:
bool storageCellCountIsSet() const;
void unsetStorage_cell_count();
/// <summary>
///
/// Use internal frame generator in FPGA instead of getting data from a real detector
/// </summary>
bool isInternalFrameGenerator() const;
void setInternalFrameGenerator(bool const value);
bool internalFrameGeneratorIsSet() const;
void unsetInternal_frame_generator();
/// <summary>
///
/// Turn off conversion of pixel read-out to photon count
/// </summary>
bool isCollectRawData() const;
void setCollectRawData(bool const value);
@@ -112,12 +112,26 @@ public:
bool pedestalG2FramesIsSet() const;
void unsetPedestal_g2_frames();
/// <summary>
///
/// Delay between two storage cells
/// </summary>
int64_t getStorageCellDelayNs() const;
void setStorageCellDelayNs(int64_t const value);
bool storageCellDelayNsIsSet() const;
void unsetStorage_cell_delay_ns();
/// <summary>
/// Fix gain to G1 (can be useful for storage cells)
/// </summary>
bool isFixedGainG1() const;
void setFixedGainG1(bool const value);
bool fixedGainG1IsSet() const;
void unsetFixed_gain_g1();
/// <summary>
/// Use high G0 (for low energy applications)
/// </summary>
bool isUseGainHg0() const;
void setUseGainHg0(bool const value);
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);
@@ -140,6 +154,10 @@ protected:
bool m_Pedestal_g2_framesIsSet;
int64_t m_Storage_cell_delay_ns;
bool m_Storage_cell_delay_nsIsSet;
bool m_Fixed_gain_g1;
bool m_Fixed_gain_g1IsSet;
bool m_Use_gain_hg0;
bool m_Use_gain_hg0IsSet;
};
+59 -1
View File
@@ -23,8 +23,12 @@ Measurement_statistics::Measurement_statistics()
{
m_File_prefix = "";
m_File_prefixIsSet = false;
m_Images_expected = 0L;
m_Images_expectedIsSet = false;
m_Images_collected = 0L;
m_Images_collectedIsSet = false;
m_Images_sent = 0L;
m_Images_sentIsSet = false;
m_Max_image_number_sent = 0L;
m_Max_image_number_sentIsSet = false;
m_Collection_efficiency = 0.0f;
@@ -67,7 +71,7 @@ bool Measurement_statistics::validate(std::stringstream& msg, const std::string&
bool success = true;
const std::string _pathPrefix = pathPrefix.empty() ? "Measurement_statistics" : pathPrefix;
if (collectionEfficiencyIsSet())
{
const float& value = m_Collection_efficiency;
@@ -113,9 +117,15 @@ bool Measurement_statistics::operator==(const Measurement_statistics& rhs) const
((!filePrefixIsSet() && !rhs.filePrefixIsSet()) || (filePrefixIsSet() && rhs.filePrefixIsSet() && getFilePrefix() == rhs.getFilePrefix())) &&
((!imagesExpectedIsSet() && !rhs.imagesExpectedIsSet()) || (imagesExpectedIsSet() && rhs.imagesExpectedIsSet() && getImagesExpected() == rhs.getImagesExpected())) &&
((!imagesCollectedIsSet() && !rhs.imagesCollectedIsSet()) || (imagesCollectedIsSet() && rhs.imagesCollectedIsSet() && getImagesCollected() == rhs.getImagesCollected())) &&
((!imagesSentIsSet() && !rhs.imagesSentIsSet()) || (imagesSentIsSet() && rhs.imagesSentIsSet() && getImagesSent() == rhs.getImagesSent())) &&
((!maxImageNumberSentIsSet() && !rhs.maxImageNumberSentIsSet()) || (maxImageNumberSentIsSet() && rhs.maxImageNumberSentIsSet() && getMaxImageNumberSent() == rhs.getMaxImageNumberSent())) &&
@@ -158,8 +168,12 @@ void to_json(nlohmann::json& j, const Measurement_statistics& o)
j = nlohmann::json();
if(o.filePrefixIsSet())
j["file_prefix"] = o.m_File_prefix;
if(o.imagesExpectedIsSet())
j["images_expected"] = o.m_Images_expected;
if(o.imagesCollectedIsSet())
j["images_collected"] = o.m_Images_collected;
if(o.imagesSentIsSet())
j["images_sent"] = o.m_Images_sent;
if(o.maxImageNumberSentIsSet())
j["max_image_number_sent"] = o.m_Max_image_number_sent;
if(o.collectionEfficiencyIsSet())
@@ -190,11 +204,21 @@ void from_json(const nlohmann::json& j, Measurement_statistics& o)
j.at("file_prefix").get_to(o.m_File_prefix);
o.m_File_prefixIsSet = true;
}
if(j.find("images_expected") != j.end())
{
j.at("images_expected").get_to(o.m_Images_expected);
o.m_Images_expectedIsSet = true;
}
if(j.find("images_collected") != j.end())
{
j.at("images_collected").get_to(o.m_Images_collected);
o.m_Images_collectedIsSet = true;
}
if(j.find("images_sent") != j.end())
{
j.at("images_sent").get_to(o.m_Images_sent);
o.m_Images_sentIsSet = true;
}
if(j.find("max_image_number_sent") != j.end())
{
j.at("max_image_number_sent").get_to(o.m_Max_image_number_sent);
@@ -265,6 +289,23 @@ void Measurement_statistics::unsetFile_prefix()
{
m_File_prefixIsSet = false;
}
int64_t Measurement_statistics::getImagesExpected() const
{
return m_Images_expected;
}
void Measurement_statistics::setImagesExpected(int64_t const value)
{
m_Images_expected = value;
m_Images_expectedIsSet = true;
}
bool Measurement_statistics::imagesExpectedIsSet() const
{
return m_Images_expectedIsSet;
}
void Measurement_statistics::unsetImages_expected()
{
m_Images_expectedIsSet = false;
}
int64_t Measurement_statistics::getImagesCollected() const
{
return m_Images_collected;
@@ -282,6 +323,23 @@ void Measurement_statistics::unsetImages_collected()
{
m_Images_collectedIsSet = false;
}
int64_t Measurement_statistics::getImagesSent() const
{
return m_Images_sent;
}
void Measurement_statistics::setImagesSent(int64_t const value)
{
m_Images_sent = value;
m_Images_sentIsSet = true;
}
bool Measurement_statistics::imagesSentIsSet() const
{
return m_Images_sentIsSet;
}
void Measurement_statistics::unsetImages_sent()
{
m_Images_sentIsSet = false;
}
int64_t Measurement_statistics::getMaxImageNumberSent() const
{
return m_Max_image_number_sent;
+18
View File
@@ -68,6 +68,13 @@ public:
/// <summary>
///
/// </summary>
int64_t getImagesExpected() const;
void setImagesExpected(int64_t const value);
bool imagesExpectedIsSet() const;
void unsetImages_expected();
/// <summary>
///
/// </summary>
int64_t getImagesCollected() const;
void setImagesCollected(int64_t const value);
bool imagesCollectedIsSet() const;
@@ -75,6 +82,13 @@ public:
/// <summary>
///
/// </summary>
int64_t getImagesSent() const;
void setImagesSent(int64_t const value);
bool imagesSentIsSet() const;
void unsetImages_sent();
/// <summary>
///
/// </summary>
int64_t getMaxImageNumberSent() const;
void setMaxImageNumberSent(int64_t const value);
bool maxImageNumberSentIsSet() const;
@@ -148,8 +162,12 @@ public:
protected:
std::string m_File_prefix;
bool m_File_prefixIsSet;
int64_t m_Images_expected;
bool m_Images_expectedIsSet;
int64_t m_Images_collected;
bool m_Images_collectedIsSet;
int64_t m_Images_sent;
bool m_Images_sentIsSet;
int64_t m_Max_image_number_sent;
bool m_Max_image_number_sentIsSet;
float m_Collection_efficiency;
+179
View File
@@ -0,0 +1,179 @@
/**
* Jungfraujoch
* Jungfraujoch Broker Web API
*
* The version of the OpenAPI document: 1.0.0
*
*
* NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech).
* https://openapi-generator.tech
* Do not edit the class manually.
*/
#include "Rotation_axis.h"
#include "Helpers.h"
#include <sstream>
namespace org::openapitools::server::model
{
Rotation_axis::Rotation_axis()
{
m_Step = 0.0f;
m_Start = 0.0f;
m_StartIsSet = false;
m_VectorIsSet = false;
}
void Rotation_axis::validate() const
{
std::stringstream msg;
if (!validate(msg))
{
throw org::openapitools::server::helpers::ValidationException(msg.str());
}
}
bool Rotation_axis::validate(std::stringstream& msg) const
{
return validate(msg, "");
}
bool Rotation_axis::validate(std::stringstream& msg, const std::string& pathPrefix) const
{
bool success = true;
const std::string _pathPrefix = pathPrefix.empty() ? "Rotation_axis" : pathPrefix;
if (vectorIsSet())
{
const std::vector<float>& value = m_Vector;
const std::string currentValuePath = _pathPrefix + ".vector";
if (value.size() < 3)
{
success = false;
msg << currentValuePath << ": must have at least 3 elements;";
}
if (value.size() > 3)
{
success = false;
msg << currentValuePath << ": must have at most 3 elements;";
}
{ // Recursive validation of array elements
const std::string oldValuePath = currentValuePath;
int i = 0;
for (const float& value : value)
{
const std::string currentValuePath = oldValuePath + "[" + std::to_string(i) + "]";
i++;
}
}
}
return success;
}
bool Rotation_axis::operator==(const Rotation_axis& rhs) const
{
return
(getStep() == rhs.getStep())
&&
((!startIsSet() && !rhs.startIsSet()) || (startIsSet() && rhs.startIsSet() && getStart() == rhs.getStart())) &&
((!vectorIsSet() && !rhs.vectorIsSet()) || (vectorIsSet() && rhs.vectorIsSet() && getVector() == rhs.getVector()))
;
}
bool Rotation_axis::operator!=(const Rotation_axis& rhs) const
{
return !(*this == rhs);
}
void to_json(nlohmann::json& j, const Rotation_axis& o)
{
j = nlohmann::json();
j["step"] = o.m_Step;
if(o.startIsSet())
j["start"] = o.m_Start;
if(o.vectorIsSet() || !o.m_Vector.empty())
j["vector"] = o.m_Vector;
}
void from_json(const nlohmann::json& j, Rotation_axis& o)
{
j.at("step").get_to(o.m_Step);
if(j.find("start") != j.end())
{
j.at("start").get_to(o.m_Start);
o.m_StartIsSet = true;
}
if(j.find("vector") != j.end())
{
j.at("vector").get_to(o.m_Vector);
o.m_VectorIsSet = true;
}
}
float Rotation_axis::getStep() const
{
return m_Step;
}
void Rotation_axis::setStep(float const value)
{
m_Step = value;
}
float Rotation_axis::getStart() const
{
return m_Start;
}
void Rotation_axis::setStart(float const value)
{
m_Start = value;
m_StartIsSet = true;
}
bool Rotation_axis::startIsSet() const
{
return m_StartIsSet;
}
void Rotation_axis::unsetStart()
{
m_StartIsSet = false;
}
std::vector<float> Rotation_axis::getVector() const
{
return m_Vector;
}
void Rotation_axis::setVector(std::vector<float> const value)
{
m_Vector = value;
m_VectorIsSet = true;
}
bool Rotation_axis::vectorIsSet() const
{
return m_VectorIsSet;
}
void Rotation_axis::unsetVector()
{
m_VectorIsSet = false;
}
} // namespace org::openapitools::server::model
+95
View File
@@ -0,0 +1,95 @@
/**
* Jungfraujoch
* Jungfraujoch Broker Web API
*
* The version of the OpenAPI document: 1.0.0
*
*
* NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech).
* https://openapi-generator.tech
* Do not edit the class manually.
*/
/*
* Rotation_axis.h
*
* Definition of a crystal rotation axis
*/
#ifndef Rotation_axis_H_
#define Rotation_axis_H_
#include <vector>
#include <nlohmann/json.hpp>
namespace org::openapitools::server::model
{
/// <summary>
/// Definition of a crystal rotation axis
/// </summary>
class Rotation_axis
{
public:
Rotation_axis();
virtual ~Rotation_axis() = default;
/// <summary>
/// Validate the current data in the model. Throws a ValidationException on failure.
/// </summary>
void validate() const;
/// <summary>
/// Validate the current data in the model. Returns false on error and writes an error
/// message into the given stringstream.
/// </summary>
bool validate(std::stringstream& msg) const;
/// <summary>
/// Helper overload for validate. Used when one model stores another model and calls it's validate.
/// Not meant to be called outside that case.
/// </summary>
bool validate(std::stringstream& msg, const std::string& pathPrefix) const;
bool operator==(const Rotation_axis& rhs) const;
bool operator!=(const Rotation_axis& rhs) const;
/////////////////////////////////////////////
/// Rotation_axis members
/// <summary>
/// Angle step in degrees
/// </summary>
float getStep() const;
void setStep(float const value);
/// <summary>
/// Start angle in degrees
/// </summary>
float getStart() const;
void setStart(float const value);
bool startIsSet() const;
void unsetStart();
/// <summary>
/// Rotation axis - vector with only zeros means using default value (set in a configuration file)
/// </summary>
std::vector<float> getVector() const;
void setVector(std::vector<float> const value);
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);
protected:
float m_Step;
float m_Start;
bool m_StartIsSet;
std::vector<float> m_Vector;
bool m_VectorIsSet;
};
} // namespace org::openapitools::server::model
#endif /* Rotation_axis_H_ */
+207 -11
View File
@@ -5,6 +5,32 @@ info:
version: 1.0.0
components:
schemas:
rotation_axis:
description: Definition of a crystal rotation axis
type: object
required:
- step
properties:
step:
type: number
format: float
example: 0.1
description: Angle step in degrees
start:
type: number
format: float
example: 50
description: Start angle in degrees
default: 0
vector:
type: array
description: Rotation axis - vector with only zeros means using default value (set in a configuration file)
default: [ 0, 0, 0 ]
items:
type: number
format: float
minItems: 3
maxItems: 3
dataset_settings:
type: object
required:
@@ -115,6 +141,39 @@ components:
description: |
/entry/instrument/attenuator/attenuator_transmission
Transmission of attenuator (filter) [no units]
omega:
$ref: "#/components/schemas/rotation_axis"
header_appendix:
type: string
description: Header appendix, added as user_data to start message
image_appendix:
type: string
description: Image appendix, added as user_data to image message
roi_sum_area:
type: object
description: Rectangle for ROI summation
required:
- x_min
- x_max
- y_min
- y_max
properties:
x_min:
type: integer
format: int64
example: 12
x_max:
type: integer
format: int64
example: 14
y_min:
type: integer
format: int64
example: 25
y_max:
type: integer
format: int64
example: 32
unit_cell:
type: object
description: Units of angstrom and degree
@@ -150,7 +209,6 @@ components:
type: number
format: float
example: 90
detector_settings:
type: object
required:
@@ -174,9 +232,11 @@ components:
internal_frame_generator:
type: boolean
default: false
description: Use internal frame generator in FPGA instead of getting data from a real detector
collect_raw_data:
type: boolean
default: false
description: Turn off conversion of pixel read-out to photon count
pedestal_g0_frames:
type: integer
format: int64
@@ -192,6 +252,15 @@ components:
storage_cell_delay_ns:
type: integer
format: int64
description: Delay between two storage cells
fixed_gain_g1:
type: boolean
default: false
description: Fix gain to G1 (can be useful for storage cells)
use_gain_hg0:
type: boolean
default: false
description: Use high G0 (for low energy applications)
spot_finding_settings:
type: object
required:
@@ -308,9 +377,15 @@ components:
properties:
file_prefix:
type: string
images_expected:
type: integer
format: int64
images_collected:
type: integer
format: int64
images_sent:
type: integer
format: int64
max_image_number_sent:
type: integer
format: int64
@@ -374,12 +449,6 @@ components:
example: 0.10
minimum: 0.0
maximum: 1.0
receiver_send_buffers_avail:
type: number
format: float
example: 0.8
minimum: 0.0
maximum: 1.0
plot_request:
type: object
properties:
@@ -828,10 +897,15 @@ paths:
schema:
type: string
description: Exception error
/plot/adu_histogram:
get:
summary: Generate ADU histogram
description: ADU histogram for all images within current data collection
/plot/saturated_pixel:
post:
summary: Generate saturated pixels plot
description: Count of saturated pixels per image; binning is configurable
requestBody:
content:
application/json:
schema:
$ref: '#/components/schemas/plot_request'
responses:
"200":
description: Everything OK
@@ -839,6 +913,128 @@ paths:
application/json:
schema:
$ref: '#/components/schemas/plot'
"400":
description: Input parsing or validation error
content:
text/plain:
schema:
type: string
description: Exception error
/plot/error_pixel:
post:
summary: Generate error pixels plot
description: Count of error pixels per image; binning is configurable
requestBody:
content:
application/json:
schema:
$ref: '#/components/schemas/plot_request'
responses:
"200":
description: Everything OK
content:
application/json:
schema:
$ref: '#/components/schemas/plot'
"400":
description: Input parsing or validation error
content:
text/plain:
schema:
type: string
description: Exception error
/plot/strong_pixel:
post:
summary: Generate strong pixels plot
description: Count of strong pixels per image (from spot finding); binning is configurable
requestBody:
content:
application/json:
schema:
$ref: '#/components/schemas/plot_request'
responses:
"200":
description: Everything OK
content:
application/json:
schema:
$ref: '#/components/schemas/plot'
"400":
description: Input parsing or validation error
content:
text/plain:
schema:
type: string
description: Exception error
/plot/roi_sum:
post:
summary: Generate ROI sum plot
description: Sum of ROI rectangle per image; binning is configurable
requestBody:
content:
application/json:
schema:
$ref: '#/components/schemas/plot_request'
responses:
"200":
description: Everything OK
content:
application/json:
schema:
$ref: '#/components/schemas/plot'
"400":
description: Input parsing or validation error
content:
text/plain:
schema:
type: string
description: Exception error
/plot/receiver_delay:
post:
summary: Generate receiver delay plot
description: Amount of frames the receiver is behind the FPGA for each image - used for internal debugging; binning is configurable
requestBody:
content:
application/json:
schema:
$ref: '#/components/schemas/plot_request'
responses:
"200":
description: Everything OK
content:
application/json:
schema:
$ref: '#/components/schemas/plot'
"400":
description: Input parsing or validation error
content:
text/plain:
schema:
type: string
description: Exception error
/plot/image_collection_efficiency:
post:
summary: Generate image collection efficiency plot
description: Ratio of collected and expected packets per image; binning is configurable
requestBody:
content:
application/json:
schema:
$ref: '#/components/schemas/plot_request'
responses:
"200":
description: Everything OK
content:
application/json:
schema:
$ref: '#/components/schemas/plot'
"400":
description: Input parsing or validation error
content:
text/plain:
schema:
type: string
description: Exception error
/plot/indexing_rate_per_file:
get:
summary: Generate indexing rate per file
+22 -11
View File
@@ -12,7 +12,7 @@
#include "JFJochBrokerHttp.h"
#include "JFJochBrokerParser.h"
#include "../frame_serialize/ZMQStream2Pusher.h"
#include "../frame_serialize/ZMQStream2PusherGroup.h"
static Pistache::Http::Endpoint *httpEndpoint;
@@ -70,8 +70,8 @@ int main (int argc, char **argv) {
}
std::unique_ptr<JFJochReceiverService> receiver;
std::unique_ptr<ZMQStream2Pusher> image_pusher;
std::unique_ptr<ZMQPreviewPublisher> preview_publisher;
std::unique_ptr<ZMQStream2PusherGroup> image_pusher;
std::unique_ptr<ZMQStream2PreviewPublisher> preview_publisher;
ZMQContext context;
@@ -82,12 +82,12 @@ int main (int argc, char **argv) {
ParseAcquisitionDeviceGroup(input, "devices", aq_devices);
if (aq_devices.size() > 0) {
experiment.DataStreams(aq_devices.size());
image_pusher = std::make_unique<ZMQStream2Pusher>(context, ParseStringArray(input, "zmq_image_addr"));
image_pusher = std::make_unique<ZMQStream2PusherGroup>(context, ParseStringArray(input, "zmq_image_addr"));
receiver = std::make_unique<JFJochReceiverService>(aq_devices, logger, *image_pusher);
std::string zmq_preview_addr = ParseString(input, "zmq_preview_addr");
if (!zmq_preview_addr.empty()) {
preview_publisher = std::make_unique<ZMQPreviewPublisher>(context, zmq_preview_addr);
preview_publisher = std::make_unique<ZMQStream2PreviewPublisher>(context, zmq_preview_addr);
receiver->PreviewPublisher(preview_publisher.get());
}
@@ -101,27 +101,38 @@ int main (int argc, char **argv) {
ParseFacilityConfiguration(input, "cfg", experiment);
logger.Info("Source {} Instrument {} Default rotation axis {:.2f},{:.2f},{:.2f}",
experiment.GetSourceName(), experiment.GetInstrumentName(),
experiment.GetDefaultOmegaAxis().x,
experiment.GetDefaultOmegaAxis().y,
experiment.GetDefaultOmegaAxis().z);
Pistache::Address addr(Pistache::Ipv4::any(), Pistache::Port(http_port));
httpEndpoint = new Pistache::Http::Endpoint((addr));
std::vector<int> sigs{SIGQUIT, SIGINT, SIGTERM, SIGHUP};
setUpUnixSignals(sigs);
auto router = std::make_shared<Pistache::Rest::Router>();
auto opts = Pistache::Http::Endpoint::options().threads(8);
opts.flags(Pistache::Tcp::Options::ReuseAddr);
httpEndpoint->init(opts);
std::vector<int> sigs{SIGQUIT, SIGINT, SIGTERM, SIGHUP};
setUpUnixSignals(sigs);
JFJochBrokerHttp broker(experiment, router);
broker.FrontendDirectory(input["frontend_directory"]);
ParseDetectorSetup(input, "detectors", broker);
if (receiver)
broker.Services().Receiver(receiver.get());
if (input["verbose"].is_boolean()) {
logger.Verbose(input["verbose"]);
aq_devices.EnableLogging(&logger);
}
// broker.Services().Detector();
if (receiver) {
broker.Services().Receiver(receiver.get());
broker.Services().Detector();
}
httpEndpoint->setHandler(router->handler());
httpEndpoint->serve();
File diff suppressed because one or more lines are too long
+15 -1
View File
@@ -6,6 +6,14 @@ ADUHistogram::ADUHistogram() : histogram(ADU_HISTO_BIN_COUNT) {
}
void ADUHistogram::Add(const std::vector<uint64_t>& input) {
std::unique_lock<std::mutex> ul(m);
if (input.size() != ADU_HISTO_BIN_COUNT)
throw JFJochException(JFJochExceptionCategory::InputParameterInvalid, "Wrong vector input to ADUHistogram::Add");
for (int i = 0; i < ADU_HISTO_BIN_COUNT; i++)
histogram[i] += input[i];
}
void ADUHistogram::Add(const DeviceOutput &output) {
std::unique_lock<std::mutex> ul(m);
for (int i = 0; i < ADU_HISTO_BIN_COUNT; i++)
@@ -26,4 +34,10 @@ Plot ADUHistogram::GetPlot() const {
ret.y[i] = histogram[i];
}
return ret;
}
}
void ADUHistogram::Restart() {
std::unique_lock<std::mutex> ul(m);
for (int i = 0; i < ADU_HISTO_BIN_COUNT; i++)
histogram[i] = 0;
}
+2
View File
@@ -12,9 +12,11 @@ class ADUHistogram {
std::vector<uint64_t> histogram;
public:
explicit ADUHistogram();
void Add(const std::vector<uint64_t>& input);
void Add(const DeviceOutput &output);
const std::vector<uint64_t>& GetHistogram() const;
Plot GetPlot() const;
void Restart();
};
#endif //JUNGFRAUJOCH_ADUHISTOGRAM_H
+1 -3
View File
@@ -29,13 +29,11 @@ ADD_LIBRARY( CommonFunctions STATIC
JFJochException.h
Definitions.h
${CMAKE_CURRENT_BINARY_DIR}/GitInfo.cpp GitInfo.h
FrameTransformation.cpp FrameTransformation.h
ThreadSafeFIFO.h
DiffractionSpot.cpp DiffractionSpot.h
StatusVector.h
SpotToSave.h
NetworkAddressConvert.h NetworkAddressConvert.cpp
to_fixed.h
DetectorGeometry.cpp DetectorGeometry.h
DetectorModuleGeometry.cpp DetectorModuleGeometry.h
DetectorSetup.h DetectorSetup.cpp ZeroCopyReturnValue.h Histogram.h DiffractionGeometry.h
@@ -44,7 +42,7 @@ ADD_LIBRARY( CommonFunctions STATIC
ADUHistogram.cpp ADUHistogram.h
RawToConvertedGeometryCore.h
Plot.h
../fpga/host_library/DeviceOutput.h
../fpga/include/jfjoch_fpga.h
ZMQWrappers.cpp ZMQWrappers.h)
TARGET_LINK_LIBRARIES(CommonFunctions Compression JFCalibration libzmq -lrt)
+3 -55
View File
@@ -3,20 +3,15 @@
#ifndef DEFINITIONS_H
#define DEFINITIONS_H
#define WVL_1A_IN_KEV 12.39854f
#include "../fpga/include/jfjoch_fpga.h"
#define DELAY_FRAMES_STOP_AND_QUIT 5
#define RAW_MODULE_LINES (512L)
#define RAW_MODULE_COLS (1024L)
#define RAW_MODULE_SIZE (RAW_MODULE_LINES * RAW_MODULE_COLS)
#define WVL_1A_IN_KEV 12.39854f
#define CONVERTED_MODULE_LINES (514L)
#define CONVERTED_MODULE_COLS (1030L)
#define CONVERTED_MODULE_SIZE (CONVERTED_MODULE_LINES * CONVERTED_MODULE_COLS)
#define JUNGFRAU_PACKET_SIZE_BYTES (8192)
#define FPGA_BUFFER_LOCATION_SIZE (RAW_MODULE_SIZE * sizeof(short) * 4) // account for space for data processing results and 32-bit frames
#define MIN_COUNT_TIME_IN_US 5
#define MIN_FRAME_TIME_HALF_SPEED_IN_US 1000
#define MIN_FRAME_TIME_FULL_SPEED_IN_US 470
@@ -27,58 +22,11 @@
#define MIN_ENERGY 0.1
#define MAX_ENERGY 25.0
#define PEDESTAL_WINDOW_SIZE 128
#define PEDESTAL_WRONG 16384
#define FRAME_TIME_PEDE_G1G2_IN_US (10*1000)
#define GAIN_G0_MULTIPLIER 32
#define GAIN_G1_MULTIPLIER (-1)
#define GAIN_G2_MULTIPLIER (-1)
#define DEFAULT_G0_FACTOR (41.0)
#define DEFAULT_G1_FACTOR (-1.439)
#define DEFAULT_G2_FACTOR (-0.1145)
#define TASK_NO_DATA_STREAM UINT16_MAX
// For FPGA
#define ACTION_TYPE 0x52324158
#define RELEASE_LEVEL 0x004A
#define MODE_CONV 0x0001L
#define MODE_32BIT 0x0002L
#define MODE_UNSIGNED 0x0004L
#define MODE_PEDESTAL_G0 0x0010L
#define MODE_PEDESTAL_G1 0x0020L
#define MODE_PEDESTAL_G2 0x0040L
#define STREAM_MERGE_SRC_NONE 0
#define STREAM_MERGE_SRC_100G 1
#define STREAM_MERGE_SRC_4x10G 2
#define STREAM_MERGE_SRC_FRAME_GEN 3
#define PIXEL_OUT_LOST (INT16_MIN)
#define LOAD_CALIBRATION_DEST_CALIB 0
#define LOAD_CALIBRATION_DEST_INTEGRATION 1
#define LOAD_CALIBRATION_DEST_FRAME_GEN 2
#define HANDLE_START (65534)
#define HANDLE_END (65535)
#define INT_PKT_GEN_DEBUG 0x0
#define INT_PKT_GEN_BUNCHID 0xCACACACACA
#define INT_PKT_GEN_EXPTTIME 10000
#define FPGA_INTEGRATION_BIN_COUNT 1024
#define MAX_MODULES_FPGA 32
#define MAX_FPGA_SUMMATION 256
#define ADU_HISTO_BIN_WIDTH 32
#define ADU_HISTO_BIN_COUNT (65536/ ADU_HISTO_BIN_WIDTH)
#define DMA_DESCRIPTORS_PER_MODULE 5
#define DEFAULT_HG0_FACTOR (100.0)
#endif //DEFINITIONS_H
+22
View File
@@ -98,3 +98,25 @@ int64_t DetectorGeometry::GetSlowDirectionStep(int64_t m) const {
throw JFJochException(JFJochExceptionCategory::ArrayOutOfBounds, "Wrong module number");
return GetDirectionStep(modules[m].GetSlowAxis());
}
Coord DetectorGeometry::GetFastDirection(int64_t module_number) const {
return GetDirection(modules[module_number].GetFastAxis());
}
Coord DetectorGeometry::GetSlowDirection(int64_t module_number) const {
return GetDirection(modules[module_number].GetSlowAxis());
}
Coord DetectorGeometry::GetDirection(DetectorModuleGeometry::Direction direction) {
switch (direction) {
case DetectorModuleGeometry::Direction::Xneg:
return {-1, 0, 0};
case DetectorModuleGeometry::Direction::Yneg:
return { 0, -1, 0};
case DetectorModuleGeometry::Direction::Ypos:
return { 0, 1, 0};
default:
case DetectorModuleGeometry::Direction::Xpos:
return { 1, 0, 0};
}
}
+4
View File
@@ -5,6 +5,7 @@
#include <cstdint>
#include <vector>
#include "Coord.h"
#include "DetectorModuleGeometry.h"
class DetectorGeometry {
@@ -12,6 +13,7 @@ class DetectorGeometry {
int64_t height;
std::vector<DetectorModuleGeometry> modules;
[[nodiscard]] int64_t GetDirectionStep(DetectorModuleGeometry::Direction direction) const;
[[nodiscard]] static Coord GetDirection(DetectorModuleGeometry::Direction direction) ;
public:
DetectorGeometry(const std::vector<DetectorModuleGeometry> &pixel_0);
DetectorGeometry(int32_t nmodules,
@@ -25,6 +27,8 @@ public:
[[nodiscard]] int64_t GetPixel0(int64_t module_number) const;
[[nodiscard]] int64_t GetFastDirectionStep(int64_t module_number) const;
[[nodiscard]] int64_t GetSlowDirectionStep(int64_t module_number) const;
[[nodiscard]] Coord GetFastDirection(int64_t module_number) const;
[[nodiscard]] Coord GetSlowDirection(int64_t module_number) const;
};
#endif //JUNGFRAUJOCH_DETECTORGEOMETRY_H
+172 -26
View File
@@ -14,6 +14,8 @@
DiffractionExperiment::DiffractionExperiment() : DiffractionExperiment(DetectorGeometry(8, 2)) {}
DiffractionExperiment::DiffractionExperiment(const DetectorSetup& det_setup) : detector(det_setup) {
default_omega_axis = {1, 0, 0};
dataset.photon_energy_keV = WVL_1A_IN_KEV;
dataset.detector_distance_mm = 100;
@@ -29,8 +31,9 @@ DiffractionExperiment::DiffractionExperiment(const DetectorSetup& det_setup) : d
dataset.compression = CompressionAlgorithm::BSHUF_LZ4;
dataset.rad_int_polarization_corr = false;
dataset.rad_int_solid_angle_corr = false;
dataset.rad_int_solid_angle_corr = true;
dataset.save_calibration = false;
dataset.omega_rotation_axis = default_omega_axis;
internal_fpga_packet_generator = false;
@@ -63,6 +66,11 @@ DiffractionExperiment::DiffractionExperiment(const DetectorSetup& det_setup) : d
pedestal_g1_frames = 0;
pedestal_g2_frames = 0;
fix_gain_g1 = false;
use_gain_hg0 = false;
series_id = 0;
Mode(DetectorMode::Conversion);
}
@@ -223,36 +231,36 @@ DiffractionExperiment &DiffractionExperiment::MaskChipEdges(bool input) {
return *this;
}
DiffractionExperiment& DiffractionExperiment::LowResForRadialInt_A(float input) {
check_min("Low Resolution for radial integration", input, 0.1);
check_max("Low Resolution for radial integration", input, 500.0);
DiffractionExperiment& DiffractionExperiment::LowResForAzimInt_A(float input) {
check_min("Low Resolution for azimuthal integration", input, 0.1);
check_max("Low Resolution for azimuthal integration", input, 500.0);
low_q = 2 * static_cast<float>(M_PI) / input;
return *this;
}
DiffractionExperiment& DiffractionExperiment::HighResForRadialInt_A(float input) {
check_min("High Resolution for radial integration", input, 0.1);
check_max("High Resolution for radial integration", input, 500.0);
DiffractionExperiment& DiffractionExperiment::HighResForAzimInt_A(float input) {
check_min("High Resolution for azimuthal integration", input, 0.1);
check_max("High Resolution for azimuthal integration", input, 500.0);
high_q = 2 * static_cast<float>(M_PI) / input;
return *this;
}
DiffractionExperiment& DiffractionExperiment::LowQForRadialInt_recipA(float input) {
check_min("Low Q for radial integration", input, 0.001);
check_max("Low Q for radial integration", input, 10.0);
DiffractionExperiment& DiffractionExperiment::LowQForAzimInt_recipA(float input) {
check_min("Low Q for azimuthal integration", input, 0.001);
check_max("Low Q for azimuthal integration", input, 10.0);
low_q = input;
return *this;
}
DiffractionExperiment& DiffractionExperiment::HighQForRadialInt_recipA(float input) {
check_min("High Q for radial integration", input, 0.001);
check_max("High Q for radial integration", input, 10.0);
DiffractionExperiment& DiffractionExperiment::HighQForAzimInt_recipA(float input) {
check_min("High Q for azimuthal integration", input, 0.001);
check_max("High Q for azimuthal integration", input, 10.0);
high_q = input;
return *this;
}
DiffractionExperiment& DiffractionExperiment::QSpacingForRadialInt_recipA(float input) {
check_min("Q spacing for radial integration", input, 0.01);
DiffractionExperiment& DiffractionExperiment::QSpacingForAzimInt_recipA(float input) {
check_min("Q spacing for azimuthal integration", input, 0.01);
q_spacing = input;
return *this;
}
@@ -460,7 +468,10 @@ std::string DiffractionExperiment::GetFilePrefix() const {
}
int64_t DiffractionExperiment::GetDataFileCount() const {
return dataset.data_file_count;
if (GetStorageCellNumber() > 1)
return GetStorageCellNumber();
else
return dataset.data_file_count;
}
CompressionAlgorithm DiffractionExperiment::GetCompressionAlgorithm() const {
@@ -510,15 +521,16 @@ int64_t DiffractionExperiment::GetDataStreamsNum() const {
}
int64_t DiffractionExperiment::GetModulesNum(uint16_t data_stream) const {
if (data_stream == TASK_NO_DATA_STREAM)
return detector.GetModulesNum();
if (data_stream >= GetDataStreamsNum())
if (data_stream >= GetDataStreamsNum())
throw JFJochException(JFJochExceptionCategory::ArrayOutOfBounds, "Non existing data stream");
return (detector.GetModulesNum() + (GetDataStreamsNum() - 1) - data_stream) / GetDataStreamsNum();
}
int64_t DiffractionExperiment::GetModulesNum() const {
return detector.GetModulesNum();
}
int64_t DiffractionExperiment::GetFirstModuleOfDataStream(uint16_t data_stream) const {
if (data_stream >= GetDataStreamsNum())
throw JFJochException(JFJochExceptionCategory::ArrayOutOfBounds, "Non exisiting data stream");
@@ -666,14 +678,14 @@ int64_t DiffractionExperiment::GetStorageCellStart() const {
return storage_cell_start;
}
float DiffractionExperiment::GetLowQForRadialInt_recipA() const {
float DiffractionExperiment::GetLowQForAzimInt_recipA() const {
return low_q;
}
float DiffractionExperiment::GetHighQForRadialInt_recipA() const {
float DiffractionExperiment::GetHighQForAzimInt_recipA() const {
return high_q;
}
float DiffractionExperiment::GetQSpacingForRadialInt_recipA() const {
float DiffractionExperiment::GetQSpacingForAzimInt_recipA() const {
return q_spacing;
}
@@ -707,8 +719,10 @@ SpotFindingSettings DiffractionExperiment::DefaultDataProcessingSettings() {
SpotFindingSettings ret{};
ret.signal_to_noise_threshold = 3;
ret.photon_count_threshold = 16;
ret.min_pix_per_spot = 1;
ret.min_pix_per_spot = 2;
ret.max_pix_per_spot = 50;
ret.low_resolution_limit = 20.0;
ret.high_resolution_limit = 2.5;
return ret;
}
@@ -721,8 +735,8 @@ void DiffractionExperiment::FillMessage(StartMessage &message) const {
message.incident_energy = GetPhotonEnergy_keV() * 1e3f;
message.image_size_x = GetXPixelsNum();
message.image_size_y = GetYPixelsNum();
message.min_value = GetUnderflow();
message.saturation_value = GetOverflow();
message.saturation_value = GetOverflow() - 1;
message.error_value = GetUnderflow();
message.frame_time = GetImageTime().count() * 1e-6f;
message.count_time = GetImageCountTime().count() * 1e-6f;
message.number_of_images = GetImageNum();
@@ -756,6 +770,15 @@ void DiffractionExperiment::FillMessage(StartMessage &message) const {
message.instrument_name = GetInstrumentName();
message.instrument_name_short = GetInstrumentNameShort();
message.summation = GetSummation();
message.user_data = GetHeaderAppendix();
message.roi_summation_area = GetROISummation();
if (GetOmegaStep())
message.goniometer["omega"] = GoniometerAxis{.increment = GetOmegaStep().value(), .start = GetOmegaStart(),
.axis = {GetOmegaAxis().x, GetOmegaAxis().y, GetOmegaAxis().z}};
message.series_id = GetSeriesID();
message.series_unique_id = GetSeriesIDString();
}
DiffractionExperiment &DiffractionExperiment::ApplyPixelMaskInFPGA(bool input) {
@@ -973,3 +996,126 @@ std::optional<float> DiffractionExperiment::GetAttenuatorTransmission() const {
std::optional<float> DiffractionExperiment::GetTotalFlux() const {
return dataset.total_flux;
}
DiffractionExperiment &DiffractionExperiment::OmegaStep(const std::optional<float> &input) {
if (input && (input == 0.0f))
dataset.omega_step.reset();
else
dataset.omega_step = input;
return *this;
}
DiffractionExperiment &DiffractionExperiment::OmegaStart(const float input) {
dataset.omega_start = input;
return *this;
}
std::optional<float> DiffractionExperiment::GetOmegaStep() const {
return dataset.omega_step;
}
float DiffractionExperiment::GetOmegaStart() const {
return dataset.omega_start;
}
DiffractionExperiment &DiffractionExperiment::UsingGainHG0(bool input) {
use_gain_hg0 = input;
return *this;
}
DiffractionExperiment &DiffractionExperiment::FixedGainG1(bool input) {
fix_gain_g1 = input;
return *this;
}
bool DiffractionExperiment::IsFixedGainG1() const {
return fix_gain_g1;
}
bool DiffractionExperiment::IsUsingGainHG0() const {
return use_gain_hg0;
}
DiffractionExperiment &DiffractionExperiment::HeaderAppendix(const std::string &input) {
dataset.header_appendix = input;
return *this;
}
DiffractionExperiment &DiffractionExperiment::ImageAppendix(const std::string &input) {
dataset.image_appendix = input;
return *this;
}
std::string DiffractionExperiment::GetHeaderAppendix() const {
return dataset.header_appendix;
}
std::string DiffractionExperiment::GetImageAppendix() const {
return dataset.image_appendix;
}
DiffractionExperiment &DiffractionExperiment::OmegaAxis(const Coord &c) {
if (c.Length() == 0.0)
throw JFJochException(JFJochExceptionCategory::InputParameterInvalid, "Cannot use empty vector for omega");
dataset.omega_rotation_axis = c.Normalize();
return *this;
}
DiffractionExperiment &DiffractionExperiment::OmegaAxis() {
dataset.omega_rotation_axis = default_omega_axis;
return *this;
}
Coord DiffractionExperiment::GetOmegaAxis() const {
return dataset.omega_rotation_axis;
}
DiffractionExperiment &DiffractionExperiment::DefaultOmegaAxis(const Coord &c) {
if (c.Length() == 0.0)
throw JFJochException(JFJochExceptionCategory::InputParameterInvalid, "Cannot use empty vector for omega axis");
default_omega_axis = c.Normalize();
return *this;
}
Coord DiffractionExperiment::GetDefaultOmegaAxis() const {
return default_omega_axis;
}
uint64_t DiffractionExperiment::GetSeriesID() const {
return series_id;
}
std::string DiffractionExperiment::GetSeriesIDString() const {
return std::to_string(series_id) + ": " + dataset.file_prefix;
}
DiffractionExperiment &DiffractionExperiment::IncrementSeriesID() {
series_id++;
return *this;
}
Coord DiffractionExperiment::GetModuleFastDirection(uint16_t module_number) const {
return detector.GetGeometry().GetFastDirection(module_number);
}
Coord DiffractionExperiment::GetModuleSlowDirection(uint16_t module_number) const {
return detector.GetGeometry().GetSlowDirection(module_number);
}
DiffractionExperiment &DiffractionExperiment::ROISummation(const std::optional<ROIRectangle> &input) {
if (input) {
check_max("Max X for ROI summation", input->x_max, GetXPixelsNum() - 1);
check_max("Max Y for ROI summation", input->y_max, GetYPixelsNum() - 1);
check_max("Min X for ROI summation", input->x_min, input->x_max);
check_max("Min Y for ROI summation", input->y_min, input->y_max);
}
dataset.roi_sum = input;
return *this;
}
std::optional<ROIRectangle> DiffractionExperiment::GetROISummation() const {
return dataset.roi_sum;
}
+50 -9
View File
@@ -60,6 +60,8 @@ class DiffractionExperiment {
int64_t pedestal_g0_frames;
int64_t pedestal_g1_frames;
int64_t pedestal_g2_frames;
bool use_gain_hg0;
bool fix_gain_g1;
std::chrono::microseconds preview_period;
@@ -82,6 +84,9 @@ class DiffractionExperiment {
std::string instrument_name_short;
bool debug_pixel_mask;
Coord default_omega_axis;
uint64_t series_id;
// Dataset settings
struct {
@@ -112,6 +117,13 @@ class DiffractionExperiment {
bool save_calibration;
std::optional<float> total_flux;
std::optional<float> attenuator_transmission;
std::optional<float> omega_step;
float omega_start;
std::string image_appendix;
std::string header_appendix;
Coord omega_rotation_axis;
std::optional<ROIRectangle> roi_sum;
} dataset;
constexpr static const int64_t max_spot_count = 100;
@@ -151,11 +163,11 @@ public:
DiffractionExperiment& MaskChipEdges(bool input);
DiffractionExperiment& SetUnitCell(const std::optional<UnitCell> &cell);
DiffractionExperiment& LowResForRadialInt_A(float input);
DiffractionExperiment& HighResForRadialInt_A(float input);
DiffractionExperiment& LowQForRadialInt_recipA(float input);
DiffractionExperiment& HighQForRadialInt_recipA(float input);
DiffractionExperiment& QSpacingForRadialInt_recipA(float input);
DiffractionExperiment& LowResForAzimInt_A(float input);
DiffractionExperiment& HighResForAzimInt_A(float input);
DiffractionExperiment& LowQForAzimInt_recipA(float input);
DiffractionExperiment& HighQForAzimInt_recipA(float input);
DiffractionExperiment& QSpacingForAzimInt_recipA(float input);
DiffractionExperiment& SpaceGroupNumber(int64_t input);
DiffractionExperiment& StorageCells(int64_t input);
@@ -169,6 +181,18 @@ public:
DiffractionExperiment& ApplyPixelMaskInFPGA(bool input);
DiffractionExperiment& AttenuatorTransmission(const std::optional<float> &input);
DiffractionExperiment& TotalFlux(const std::optional<float> &input);
DiffractionExperiment& OmegaStep(const std::optional<float> &input);
DiffractionExperiment& OmegaStart(const float input);
DiffractionExperiment& OmegaAxis(const Coord &c);
DiffractionExperiment& OmegaAxis();
DiffractionExperiment& DefaultOmegaAxis(const Coord &c);
DiffractionExperiment& UsingGainHG0(bool input);
DiffractionExperiment& FixedGainG1(bool input);
DiffractionExperiment& HeaderAppendix(const std::string& input);
DiffractionExperiment& ImageAppendix(const std::string& input);
DiffractionExperiment& IncrementSeriesID();
DiffractionExperiment& ROISummation(const std::optional<ROIRectangle>& input);
void FillMessage(StartMessage &message) const;
@@ -217,7 +241,8 @@ public:
int64_t GetMaxCompressedSize() const;
int64_t GetDataStreamsNum() const;
int64_t GetModulesNum(uint16_t data_stream = TASK_NO_DATA_STREAM) const;
int64_t GetModulesNum(uint16_t data_stream) const;
int64_t GetModulesNum() const;
int64_t GetFirstModuleOfDataStream(uint16_t data_stream) const;
int64_t GetPixelsNum() const;
@@ -227,6 +252,9 @@ public:
int64_t GetModuleFastDirectionStep(uint16_t module_number) const;
int64_t GetModuleSlowDirectionStep(uint16_t module_number) const;
Coord GetModuleFastDirection(uint16_t module_number) const;
Coord GetModuleSlowDirection(uint16_t module_number) const;
std::chrono::microseconds GetPreviewPeriod() const;
int64_t GetPreviewStride() const;
@@ -246,9 +274,9 @@ public:
Coord LabCoord(float detector_x, float detector_y) const;
float GetLowQForRadialInt_recipA() const;
float GetHighQForRadialInt_recipA() const;
float GetQSpacingForRadialInt_recipA() const;
float GetLowQForAzimInt_recipA() const;
float GetHighQForAzimInt_recipA() const;
float GetQSpacingForAzimInt_recipA() const;
float GetLowQForBkgEstimate_recipA() const;
float GetHighQForBkgEstimate_recipA() const;
@@ -292,6 +320,19 @@ public:
std::vector<DetectorModuleConfig> GetDetectorModuleConfig(const std::vector<AcquisitionDeviceNetConfig>& net_config) const;
std::optional<float> GetAttenuatorTransmission() const;
std::optional<float> GetTotalFlux() const;
std::optional<float> GetOmegaStep() const;
float GetOmegaStart() const;
Coord GetOmegaAxis() const;
Coord GetDefaultOmegaAxis() const;
bool IsFixedGainG1() const;
bool IsUsingGainHG0() const;
std::string GetHeaderAppendix() const;
std::string GetImageAppendix() const;
uint64_t GetSeriesID() const;
std::string GetSeriesIDString() const;
std::optional<ROIRectangle> GetROISummation() const;
};
inline int64_t CalculateStride(const std::chrono::microseconds &frame_time, const std::chrono::microseconds &preview_time) {
+7
View File
@@ -2,6 +2,7 @@
#include "DiffractionSpot.h"
#include "DiffractionGeometry.h"
#include "RawToConvertedGeometry.h"
DiffractionSpot::DiffractionSpot(uint32_t col, uint32_t line, int64_t in_photons) {
if (in_photons < 0) in_photons = 0;
@@ -65,3 +66,9 @@ void DiffractionSpot::AddPixel(uint32_t col, uint32_t line, int64_t photons) {
this->max_photons = std::max(this->max_photons, photons);
this->pixel_count += 1;
}
void DiffractionSpot::ConvertToImageCoordinates(const DiffractionExperiment &experiment, uint16_t module_number) {
auto c_out = RawToConvertedCoordinate(experiment, module_number, RawCoord());
this->x = c_out.x * (float) photons;
this->y = c_out.y * (float) photons;
}
+1
View File
@@ -23,6 +23,7 @@ public:
int64_t MaxCount() const;
Coord RawCoord() const;
Coord LabCoord(const DiffractionExperiment &experiment) const;
void ConvertToImageCoordinates(const DiffractionExperiment& experiment, uint16_t module_number);
double GetResolution(const DiffractionExperiment &experiment) const;
Coord ReciprocalCoord(const DiffractionExperiment &experiment) const;
operator SpotToSave() const;
+2 -1
View File
@@ -7,7 +7,8 @@
#include <cstdint>
#include <string>
enum class PlotType {BkgEstimate, RadInt, SpotCount, IndexingRate, IndexingRatePerFile, ADUHistorgram};
enum class PlotType {BkgEstimate, RadInt, SpotCount, IndexingRate, IndexingRatePerFile, SaturatedPixels,
ErrorPixels, ImageCollectionEfficiency, ReceiverDelay, StrongPixels, ROISum};
struct PlotRequest {
PlotType type;
+12
View File
@@ -36,6 +36,18 @@ inline std::pair<int64_t, int64_t> RawToConvertedCoordinate(const DiffractionExp
return {pixel % experiment.GetXPixelsNum() , pixel / experiment.GetXPixelsNum()};
}
inline Coord RawToConvertedCoordinate(const DiffractionExperiment& experiment, uint32_t module_number, const Coord &c) {
int64_t pixel0 = experiment.GetPixel0OfModule(module_number);
Coord pixel0_coord(pixel0 % experiment.GetXPixelsNum(),
pixel0 / experiment.GetXPixelsNum(),
0);
return pixel0_coord
+ experiment.GetModuleFastDirection(module_number) * (c.x + (static_cast<int32_t>(c.x) / 256) * 2)
+ experiment.GetModuleSlowDirection(module_number) * (c.y + (static_cast<int32_t>(c.y) / 256) * 2);
}
template<class T>
void ConvertedToRawGeometry(const DiffractionExperiment &experiment, T *destination, const T *source) {
for (size_t module_number = 0; module_number < experiment.GetModulesNum(); module_number++) {
+1
View File
@@ -6,6 +6,7 @@
#include <vector>
#include <map>
#include <mutex>
#include <cmath>
#include "Plot.h"
+37 -6
View File
@@ -27,6 +27,8 @@ ZMQSocket::ZMQSocket(ZMQContext &context, ZMQSocketType in_socket_type) : socket
if (socket == nullptr)
throw JFJochException(JFJochExceptionCategory::ZeroMQ, "zmq_socket failed");
EnableKeepAlive();
}
void ZMQSocket::Bind(const std::string &addr) {
@@ -50,17 +52,21 @@ void ZMQSocket::Send() {
throw JFJochException(JFJochExceptionCategory::ZeroMQ, "zmq_send() failed: " + std::string(std::strerror(errno)));
}
void ZMQSocket::Send(const void *buf, size_t buf_size, bool blocking, bool multipart) {
bool ZMQSocket::Send(const void *buf, size_t buf_size, bool blocking, bool multipart) {
std::unique_lock<std::mutex> ul(m);
if (zmq_send(socket, buf, buf_size, (blocking ? 0 : ZMQ_DONTWAIT) | (multipart ? ZMQ_SNDMORE : 0)) != buf_size) {
if (errno != EAGAIN)
if (zmq_send(socket, buf, buf_size, (blocking ? 0 : ZMQ_DONTWAIT) | (multipart ? ZMQ_SNDMORE : 0)) == buf_size)
return true;
else {
if ((errno == EAGAIN) || (errno == EINTR))
return false;
else
throw JFJochException(JFJochExceptionCategory::ZeroMQ,
"zmq_send(buf) failed: " + std::string(std::strerror(errno)));
}
}
void ZMQSocket::Send(const std::string &s, bool blocking, bool multipart) {
Send((void *) s.c_str(), s.size(), blocking, multipart);
bool ZMQSocket::Send(const std::string &s, bool blocking, bool multipart) {
return Send((void *) s.c_str(), s.size(), blocking, multipart);
}
void ZMQSocket::Send(const int32_t &value) {
@@ -122,6 +128,16 @@ ZMQSocket &ZMQSocket::NoReceiveTimeout() {
return *this;
}
ZMQSocket &ZMQSocket::SendTimeout(std::chrono::milliseconds input) {
SetSocketOption(ZMQ_SNDTIMEO, input.count());
return *this;
}
ZMQSocket &ZMQSocket::NoSendTimeout() {
SetSocketOption(ZMQ_SNDTIMEO, -1);
return *this;
}
ZMQSocket &ZMQSocket::ReceiverBufferSize(int32_t bytes) {
SetSocketOption(ZMQ_RCVBUF, bytes);
return *this;
@@ -168,4 +184,19 @@ ZMQSocket &ZMQSocket::NoLinger() {
ZMQSocket &ZMQSocket::Conflate(bool input) {
SetSocketOption(ZMQ_CONFLATE, input ? 1 : 0);
return *this;
}
}
ZMQSocket &ZMQSocket::EnableKeepAlive() {
SetSocketOption(ZMQ_TCP_KEEPALIVE, 1);
SetSocketOption(ZMQ_TCP_KEEPALIVE_CNT, 10);
SetSocketOption(ZMQ_TCP_KEEPALIVE_IDLE, 60);
SetSocketOption(ZMQ_TCP_KEEPALIVE_INTVL, 1);
return *this;
}
std::string ZMQSocket::GetEndpointName() {
char tmp[256];
size_t len = 255;
zmq_getsockopt(socket, ZMQ_LAST_ENDPOINT, tmp, &len);
return tmp;
}
+11 -7
View File
@@ -43,6 +43,10 @@ public:
void Bind(const std::string& addr);
ZMQSocket &NoReceiveTimeout();
ZMQSocket &ReceiveTimeout(std::chrono::milliseconds input);
ZMQSocket &NoSendTimeout();
ZMQSocket &SendTimeout(std::chrono::milliseconds input);
ZMQSocket &Subscribe(const std::string &topic);
ZMQSocket &SubscribeAll();
ZMQSocket &NoLinger();
@@ -58,9 +62,7 @@ public:
zmq_msg_init(&zmq_msg);
int64_t msg_size = zmq_msg_recv(&zmq_msg, socket, blocking ? 0 : ZMQ_DONTWAIT);
if (msg_size < 0) {
if (errno == EAGAIN)
return -1;
if (errno == EINTR) // Timeout ?
if ((errno == EAGAIN) || (errno == EINTR))
return -1;
else
throw JFJochException(JFJochExceptionCategory::ZeroMQ, "zmq_msg_recv failed "
@@ -81,16 +83,18 @@ public:
}
void Send();
void Send(const void *buf, size_t buf_size, bool blocking = true, bool multipart = false);
bool Send(const void *buf, size_t buf_size, bool blocking = true, bool multipart = false);
void SendZeroCopy(const void *buf, size_t buf_size, ZeroCopyReturnValue *zero_copy_ret_val);
template <class T> void Send(const std::vector<T> &buf) {
Send(buf.data(), buf.size() * sizeof(T));
template <class T> bool Send(const std::vector<T> &buf) {
return Send(buf.data(), buf.size() * sizeof(T));
}
void Send(const int32_t &value);
void Send(const std::string &s, bool blocking = true, bool multipart = false);
bool Send(const std::string &s, bool blocking = true, bool multipart = false);
void Send(zmq_msg_t *msg);
ZMQSocket &SendWaterMark(int32_t msgs);
ZMQSocket &ReceiveWaterMark(int32_t msgs);
ZMQSocket &EnableKeepAlive();
std::string GetEndpointName();
};
-18
View File
@@ -1,18 +0,0 @@
// Copyright (2019-2023) Paul Scherrer Institute
#ifndef JUNGFRAUJOCH_TO_FIXED_H
#define JUNGFRAUJOCH_TO_FIXED_H
#include <cstdint>
#include <cmath>
inline uint16_t to_fixed(double val, uint16_t fractional_bits) {
// If val is result of division by zero, only reasonable value of output is zero (otherwise number could be interpreted improperly)
uint32_t int_val = std::isfinite(val) ? (std::lround(val * (1<<fractional_bits))) : 0;
// It is unlikely (but not impossible), that gain value will be lower than the smallest possible
// Then reciprocal of gain could be more than allowed by data format. Protection is added for this condition
if (int_val > UINT16_MAX) int_val = UINT16_MAX;
return int_val;
}
#endif //JUNGFRAUJOCH_TO_FIXED_H
+24 -10
View File
@@ -95,18 +95,32 @@ void DetectorWrapper::Start(const DiffractionExperiment& experiment) {
try {
InternalStop();
switch (experiment.GetDetectorMode()) {
case DetectorMode::PedestalG1:
det.setGainMode(slsDetectorDefs::gainMode::FORCE_SWITCH_G1);
break;
case DetectorMode::PedestalG2:
det.setGainMode(slsDetectorDefs::gainMode::FORCE_SWITCH_G2);
break;
default:
det.setGainMode(slsDetectorDefs::gainMode::DYNAMIC);
break;
if (experiment.IsFixedGainG1()) {
if ((experiment.GetDetectorMode() == DetectorMode::PedestalG0) ||
(experiment.GetDetectorMode() == DetectorMode::PedestalG2))
throw JFJochException(JFJochExceptionCategory::Detector,
"Pedestal G0/G2 doesn't make sense for fixed G1 mode");
det.setGainMode(slsDetectorDefs::FIX_G1);
} else {
switch (experiment.GetDetectorMode()) {
case DetectorMode::PedestalG1:
det.setGainMode(slsDetectorDefs::gainMode::FORCE_SWITCH_G1);
break;
case DetectorMode::PedestalG2:
det.setGainMode(slsDetectorDefs::gainMode::FORCE_SWITCH_G2);
break;
default:
det.setGainMode(slsDetectorDefs::gainMode::DYNAMIC);
break;
}
}
if (experiment.IsUsingGainHG0())
det.setSettings(slsDetectorDefs::HIGHGAIN0);
else
det.setSettings(slsDetectorDefs::GAIN0);
det.setNextFrameNumber(1);
if (experiment.GetNumTriggers() == 1) {
-1
View File
@@ -1 +0,0 @@
INSTALL(FILES broker.json DESTINATION etc)
+2 -1
View File
@@ -14,8 +14,9 @@
"preview_period_us": "1 s",
"detector_ipv4": "10.10.85.0"
},
"frontend_directory":"/home/jungfrau/nextgendcu/frontend/build",
"numa_policy": "n2g2",
"zmq_image_addr": ["tcp://10.10.1.243:5500", "tcp://10.10.1.243:5501", "tcp://10.10.1.243:5502", "tcp://10.10.1.243:5503"],
"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"],
"zmq_preview_addr": "tcp://0.0.0.0:5400",
"receiver_threads": 64,
"send_buffer_count": 2048,
+16
View File
@@ -0,0 +1,16 @@
FIND_PACKAGE(TIFF COMPONENTS CXX)
FIND_PACKAGE(JPEG)
ADD_LIBRARY(ExportImage STATIC WriteTIFF.cpp WriteTIFF.h WriteJPEG.cpp WriteJPEG.h)
IF (${TIFF_FOUND})
TARGET_COMPILE_DEFINITIONS(ExportImage PUBLIC -DJFJOCH_USE_TIFF)
TARGET_INCLUDE_DIRECTORIES(ExportImage PRIVATE ${TIFF_INCLUDE_DIR})
TARGET_LINK_LIBRARIES(ExportImage PUBLIC ${TIFF_LIBRARIES})
ENDIF()
IF (${JPEG_FOUND})
TARGET_COMPILE_DEFINITIONS(ExportImage PUBLIC -DJFJOCH_USE_JPEG)
TARGET_INCLUDE_DIRECTORIES(ExportImage PRIVATE ${JPEG_INCLUDE_DIR})
TARGET_LINK_LIBRARIES(ExportImage PUBLIC ${JPEG_LIBRARIES})
ENDIF()
+41
View File
@@ -0,0 +1,41 @@
// Copyright (2019-2024) Paul Scherrer Institute
#ifdef JFJOCH_USE_JPEG
#include <cstdio>
#include <cstdint>
#include <cstddef>
#include <vector>
#include <jpeglib.h>
#endif
void WriteJPEG(const std::vector<char> &input, size_t width, size_t height) {
unsigned char *buf;
unsigned long buf_size;
struct jpeg_compress_struct cinfo;
struct jpeg_error_mgr jerr;
cinfo.err = jpeg_std_error(&jerr);
jpeg_create_compress(&cinfo);
jpeg_mem_dest(&cinfo, &buf, &buf_size);
cinfo.image_width = width;
cinfo.image_height = height;
cinfo.input_components = 3;
cinfo.in_color_space = JCS_RGB;
jpeg_set_defaults(&cinfo);
/*set the quality [0..100] */
jpeg_set_quality (&cinfo, 75, true);
jpeg_start_compress(&cinfo, true);
JSAMPROW row_pointer; /* pointer to a single row */
while (cinfo.next_scanline < cinfo.image_height) {
row_pointer = (JSAMPROW) (input.data() + cinfo.next_scanline*(sizeof(char)>>3)*width);
jpeg_write_scanlines(&cinfo, &row_pointer, 1);
}
jpeg_finish_compress(&cinfo);
jpeg_destroy_compress(&cinfo);
}
+7
View File
@@ -0,0 +1,7 @@
// Copyright (2019-2023) Paul Scherrer Institute
#ifndef JUNGFRAUJOCH_WRITEJPEG_H
#define JUNGFRAUJOCH_WRITEJPEG_H
#endif //JUNGFRAUJOCH_WRITEJPEG_H
+60
View File
@@ -0,0 +1,60 @@
// Copyright (2019-2024) Paul Scherrer Institute
#include "WriteTIFF.h"
#include "../common/JFJochException.h"
#ifdef JFJOCH_USE_TIFF
#include <tiffio.h>
#include <tiffio.hxx>
#include <sstream>
#endif
void WriteTIFF(TIFF *tiff, void *buff, size_t cols, size_t lines, size_t elem_size, bool is_signed) {
#ifndef JFJOCH_USE_TIFF
throw JFJochException(JFJochExceptionCategory::TIFFGeneratorError, "Compiled without TIFF support");
#else
if (tiff == nullptr)
throw JFJochException(JFJochExceptionCategory::TIFFGeneratorError, "TIFFStreamOpen error");
TIFFSetField(tiff, TIFFTAG_IMAGEWIDTH, cols); // set the width of the image
TIFFSetField(tiff, TIFFTAG_IMAGELENGTH, lines); // set the height of the image
TIFFSetField(tiff, TIFFTAG_SAMPLESPERPIXEL, 1); // set number of channels per pixel
TIFFSetField(tiff, TIFFTAG_BITSPERSAMPLE, elem_size * 8); // set the size of the channels
TIFFSetField(tiff, TIFFTAG_COMPRESSION, COMPRESSION_LZW); // setc ompression to LZW
TIFFSetField(tiff, TIFFTAG_ROWSPERSTRIP, lines);
if (is_signed)
TIFFSetField(tiff, TIFFTAG_SAMPLEFORMAT, SAMPLEFORMAT_INT);
else
TIFFSetField(tiff, TIFFTAG_SAMPLEFORMAT, SAMPLEFORMAT_UINT);
if (TIFFWriteEncodedStrip(tiff, 0, buff, cols * lines * elem_size) < 0)
throw JFJochException(JFJochExceptionCategory::TIFFGeneratorError, "TIFFWriteEncodedStrip error");
#endif
}
std::string WriteTIFFToString(void *buff, size_t cols, size_t lines, size_t elem_size, bool is_signed) {
#ifndef JFJOCH_USE_TIFF
throw JFJochException(JFJochExceptionCategory::TIFFGeneratorError, "Compiled without TIFF support");
#else
std::stringstream os;
TIFF *tiff = TIFFStreamOpen("x", (std::ostream *) &os);
WriteTIFF(tiff, buff, cols, lines, elem_size, is_signed);
TIFFClose(tiff);
return os.str();
#endif
}
void WriteTIFFToFile(const std::string &filename, void *buff, size_t cols, size_t lines, size_t elem_size,
bool is_signed) {
#ifndef JFJOCH_USE_TIFF
throw JFJochException(JFJochExceptionCategory::TIFFGeneratorError, "Compiled without TIFF support");
#else
TIFF *tiff = TIFFOpen(filename.c_str(), "w");
WriteTIFF(tiff, buff, cols, lines, elem_size, is_signed);
TIFFClose(tiff);
#endif
}
+12
View File
@@ -0,0 +1,12 @@
// Copyright (2019-2024) Paul Scherrer Institute
#ifndef JUNGFRAUJOCH_WRITETIFF_H
#define JUNGFRAUJOCH_WRITETIFF_H
#include <string>
std::string WriteTIFFToString(void *buff, size_t cols, size_t lines, size_t elem_size, bool is_signed = false);
void WriteTIFFToFile(const std::string &filename, void *buff, size_t cols, size_t lines, size_t elem_size,
bool is_signed = false);
#endif //JUNGFRAUJOCH_WRITETIFF_H
+7 -3
View File
@@ -113,6 +113,10 @@ For RHEL9 this needs to built from source - [Xilinx/XRT github repository](https
Irrespective of the method use to upload firmware, it is necessary to do cold reboot the server (with a short power interruption to PCIe devices).
Currently, this is best done by powering the server off and on again. More efficient procedure is yet to be tested.
## Reset card
To reset the card it is enough to do a standard warm reboot.
Loading new image from the flash requires cold reboot, where power is cut for the card for a short time.
## Hardware verification
To test that FPGA board is working properly without access to a JUNGFRAU detector, you can use `jfjoch_action_test` tool.
@@ -123,7 +127,7 @@ This number is incremented after each change of functionality of the card or int
This ensures consistency between the FPGA card, driver and user application. Changes within the design (e.g. size of FIFOs),
that are invisible to interactions with host do not require change in release number.
To check release number, look for constant `RELEASE_NUMBER` in [common/Definitions.h](../common/Definitions.h) header file.
To check release number, look for constant `RELEASE_NUMBER` in [include/jfjoch_fpga.h](include/jfjoch_fpga.h) header file.
For FPGA design, release number is also included in the generated bitstream name.
In case there is mismatch in release number between card and kernel driver, the latter will not create the character device and return error (check `dmesg`).
@@ -172,14 +176,14 @@ FPGA setup can be done via 32-bit registers:
| 0x010060 | 64 | Valid detector packets processed by the card | R | cleared on reset |
| 0x010066 | 64 | Packets flagged as errors by CMAC | R | cleared on reset |
| 0x010100 | 32 | Spot finder photon count threshold | R/W | |
| 0x010104 | 32 | Spot finder signal-to-noise ratio threshold (in fixed-point: 6 int. + 4 frac. bit format) | R/W | |
| 0x010104 | 32 | Spot finder signal-to-noise ratio threshold (single-precision float) | R/W | |
| 0x010200 | 64 | MAC address of FPGA card | R/W | network byte order |
| 0x010208 | 32 | IPv4 address of FPGA card | R/W | network byte order |
| 0x01020C | 32 | Number of detector modules (value minus one: 0 => 1 module, 1 => 2 modules, etc.) | R/W | |
| 0x010210 | 32 | Data collection mode | R/W | |
| | | Bit 0 - Conversion to photons | | |
| | | Bit 16:31 - Data collection ID (carried with completions) | | |
| 0x010214 | 32 | One over energy in keV (in fixed-point:12 int. + 24 frac. bit format) | R/W | |
| 0x010214 | 32 | Photon energy in keV (single-precision float) | R/W | |
| 0x010218 | 32 | Number of frames expected in the data collection (defines termination condition) | R/W | |
| 0x01021C | 32 | Number of storage cells | R/W | |
| 0x010220 | 32 | Summation on card (value minus one: 0 => summation of 1, 1 => summation of 2, etc.) | R/W | |
+41 -15
View File
@@ -14,10 +14,12 @@
`define ADDR_ACTION_TYPE 16'h0010
`define ADDR_RELEASE_LEVEL 16'h0014
`define ADDR_MAX_MODULES_FPGA 16'h0020
`define ADDR_MAX_MODULES_FPGA 16'h0020
`define ADDR_RUN_COUNTER 16'h0024
`define ADDR_STALLS_HOST_LO 16'h0028
`define ADDR_STALLS_HOST_HI 16'h002C
`define ADDR_STALLS_HBM_LO 16'h0030
`define ADDR_STALLS_HBM_HI 16'h0034
`define ADDR_FIFO_STATUS 16'h0038
@@ -56,7 +58,7 @@
`define ADDR_NMODULES 16'h020C
`define ADDR_DATA_COL_MODE 16'h0210
`define ADDR_ONE_OVER_ENERGY 16'h0214
`define ADDR_ENERGY_KEV 16'h0214
`define ADDR_NFRAMES 16'h0218
`define ADDR_NSTORAGE_CELLS 16'h021C
@@ -95,21 +97,31 @@ module action_config
output reg [31:0] data_collection_mode ,
output reg [47:0] fpga_mac_addr ,
output reg [31:0] fpga_ipv4_addr ,
output reg [31:0] one_over_energy ,
output reg [31:0] energy_kev ,
output reg [31:0] nframes ,
output reg [4:0] nmodules ,
output reg [3:0] nstorage_cells ,
output reg [7:0] nsummation ,
output reg [1:0] data_source ,
output wire [31:0] hbm_size_bytes ,
output reg [15:0] spot_finder_count_threshold,
output reg [7:0] spot_finder_snr_threshold,
output reg [31:0] spot_finder_count_threshold,
output reg [31:0] spot_finder_snr_threshold,
output reg data_collection_start ,
output reg data_collection_cancel ,
input data_collection_idle ,
input host_writer_idle ,
input load_from_hbm_idle ,
input save_to_hbm_idle ,
input frame_summation_idle ,
input integration_idle ,
input stream_conv_idle ,
input udp_idle ,
input sls_detector_idle ,
input [2:0] host_writer_state ,
input calib_data_fifo_empty ,
input calib_data_fifo_full ,
input calib_addr_fifo_empty ,
@@ -214,6 +226,8 @@ localparam
reg [31:0] reg_udp_err_len;
reg [31:0] reg_udp_err_eth;
reg [31:0] reg_data_acquisition_count;
reg [31:0] reg_fifo_status;
reg reg_data_collection_idle;
//------------------------Instantiation------------------
@@ -317,8 +331,8 @@ always @(posedge clk) begin
`ADDR_DATA_COL_MODE: begin
rdata <= data_collection_mode;
end
`ADDR_ONE_OVER_ENERGY: begin
rdata <= one_over_energy;
`ADDR_ENERGY_KEV: begin
rdata <= energy_kev;
end
`ADDR_NFRAMES: begin
rdata <= nframes;
@@ -431,6 +445,9 @@ always @(posedge clk) begin
`ADDR_SPOT_FINDER_SNR_THR: begin
rdata <= spot_finder_snr_threshold;
end
`ADDR_RUN_COUNTER: begin
rdata <= reg_data_acquisition_count;
end
default:
rdata <= 32'hffffffff;
endcase
@@ -456,17 +473,26 @@ always @(posedge clk) begin
reg_ctrl[2] <= data_collection_cancel;
reg_ctrl[3] <= clear_counters;
reg_ctrl[4] <= host_writer_idle;
reg_ctrl[5] <= load_from_hbm_idle;
reg_ctrl[6] <= save_to_hbm_idle;
reg_ctrl[7] <= frame_summation_idle;
reg_ctrl[8] <= integration_idle;
reg_ctrl[9] <= stream_conv_idle;
reg_ctrl[12:10] <= host_writer_state;
reg_ctrl[16] <= mailbox_interrupt_0;
end
end
always @(posedge clk) begin
if (!resetn)
if (!resetn) begin
data_collection_start <= 1'b0;
else if (!reg_data_collection_idle)
reg_data_acquisition_count <= 32'h0;
end else if (!reg_data_collection_idle)
data_collection_start <= 1'b0;
else if (w_hs && waddr == `ADDR_AP_CTRL && s_axi_WSTRB[0] && s_axi_WDATA[0])
else if (w_hs && waddr == `ADDR_AP_CTRL && s_axi_WSTRB[0] && s_axi_WDATA[0]) begin
reg_data_acquisition_count <= reg_data_acquisition_count + 32'h1;
data_collection_start <= 1'b1;
end
end
always @(posedge clk) begin
@@ -529,10 +555,10 @@ end
always @(posedge clk) begin
if (!resetn)
one_over_energy <= 0;
energy_kev <= 0;
else if (reg_data_collection_idle) begin
if (w_hs && waddr == `ADDR_ONE_OVER_ENERGY )
one_over_energy <= (s_axi_WDATA[31:0] & wmask) | (one_over_energy & !wmask);
if (w_hs && waddr == `ADDR_ENERGY_KEV )
energy_kev <= (s_axi_WDATA[31:0] & wmask) | (energy_kev & !wmask);
end
end
@@ -585,14 +611,14 @@ always @(posedge clk) begin
if (!resetn)
spot_finder_snr_threshold <= 0;
else if (w_hs && waddr == `ADDR_SPOT_FINDER_SNR_THR)
spot_finder_snr_threshold <= (s_axi_WDATA[7:0] & wmask[7:0]) | (spot_finder_snr_threshold & !wmask[7:0]);
spot_finder_snr_threshold <= (s_axi_WDATA[31:0] & wmask[31:0]) | (spot_finder_snr_threshold & !wmask[31:0]);
end
always @(posedge clk) begin
if (!resetn)
spot_finder_count_threshold <= 0;
else if (w_hs && waddr == `ADDR_SPOT_FINDER_CNT_THR)
spot_finder_count_threshold <= (s_axi_WDATA[15:0] & wmask[15:0]) | (spot_finder_count_threshold & !wmask[15:0]);
spot_finder_count_threshold <= (s_axi_WDATA[31:0] & wmask[31:0]) | (spot_finder_count_threshold & !wmask[31:0]);
end
always @ (posedge clk) begin
+2 -2
View File
@@ -3,7 +3,7 @@ ADD_LIBRARY( HLSSimulation STATIC
data_collection_fsm.cpp
timer.cpp
hls_jfjoch.h
../../common/Definitions.h
../include/jfjoch_fpga.h
load_calibration.cpp
host_writer.cpp
ethernet.cpp
@@ -59,7 +59,7 @@ FUNCTION( MAKE_HLS_MODULE FUNCTION_NAME SRC_FILE TB_FILE)
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 ../../common/Definitions.h)
DEPENDS ${SRC_FILE} hls_jfjoch.h ../include/jfjoch_fpga.h)
SET (HLS_IPS ${HLS_IPS} psi_ch_hls_${FUNCTION_NAME}_1_0.zip PARENT_SCOPE)
ENDFUNCTION(MAKE_HLS_MODULE)
+33 -3
View File
@@ -23,14 +23,26 @@ void adu_histo(STREAM_512 &data_in,
for (int i = 0; i < 64; i++)
count[i][j] = 0;
}
ap_uint<24> saturated_pixels[32];
ap_uint<24> err_pixels[32];
for (int i = 0; i < 32; i++) {
saturated_pixels[i] = 0;
err_pixels[i] = 0;
}
ap_uint<16> in_val[32];
ap_uint<256> bins_0, bins_1;
packet_512_t packet_in;
data_in >> packet_in;
{
#pragma HLS PROTOCOL fixed
data_in >> packet_in;
ap_wait();
data_out << packet_in;
ap_wait();
}
ap_uint<8> sum = ACT_REG_NSUMMATION(packet_in.data); // 0..255
data_out << packet_in;
axis_completion cmpl;
s_axis_completion >> cmpl;
@@ -47,8 +59,13 @@ void adu_histo(STREAM_512 &data_in,
data_out << packet_in;
unpack32(packet_in.data, in_val);
for (int j = 0; j < 32; j++)
for (int j = 0; j < 32; j++) {
count[k * 32 + j][in_val[j] / ADU_HISTO_BIN_WIDTH] += (cmpl.packet_mask[i / 64] ? 1 : 0);
if (cmpl.packet_mask[i/64] && (in_val[j] == 0xc000))
saturated_pixels[j]++;
if (cmpl.packet_mask[i/64] && (in_val[j] == 0xffff))
err_pixels[j]++;
}
}
}
s_axis_completion >> cmpl;
@@ -66,6 +83,19 @@ void adu_histo(STREAM_512 &data_in,
}
result_out << val;
}
ap_uint<32> saturated_pixels_total = 0;
ap_uint<32> err_pixels_total = 0;
for (int i = 0; i < 32; i++) {
#pragma HLS UNROLL
saturated_pixels_total += saturated_pixels[i];
saturated_pixels[i] = 0;
err_pixels_total += err_pixels[i];
err_pixels[i] = 0;
}
ap_uint<512> val_sat = 0;
val_sat(31, 0) = saturated_pixels_total;
val_sat(63,32) = err_pixels_total;
result_out << val_sat;
}
m_axis_completion << cmpl;
-1
View File
@@ -106,4 +106,3 @@ void arp(AXI_STREAM &arp_in,
prev_start = arp_start;
}
+19 -18
View File
@@ -4,18 +4,19 @@
#include "hls_jfjoch.h"
void data_collection_fsm(AXI_STREAM &eth_in,
STREAM_512 &data_out,
hls::stream<axis_addr> &addr_in,
hls::stream<axis_addr> &addr_out,
volatile ap_uint<1> &in_run,
volatile ap_uint<1> &in_cancel,
volatile ap_uint<1> &out_idle,
ap_uint<32> mode,
ap_uint<32> one_over_energy,
ap_uint<32> nframes,
ap_uint<5> nmodules,
ap_uint<4> nstorage_cells,
ap_uint<8> nsummation) {
STREAM_512 &data_out,
hls::stream<axis_addr> &addr_in,
hls::stream<axis_addr> &addr_out,
volatile ap_uint<1> &in_run,
volatile ap_uint<1> &in_cancel,
volatile ap_uint<1> &out_idle,
ap_uint<32> mode,
ap_uint<32> energy_kev,
ap_uint<32> nframes,
ap_uint<5> nmodules,
ap_uint<4> nstorage_cells,
ap_uint<8> nsummation,
volatile rcv_state_t &data_collection_state) {
#pragma HLS INTERFACE ap_ctrl_none port=return
#pragma HLS INTERFACE axis register both port=eth_in
@@ -27,11 +28,12 @@ void data_collection_fsm(AXI_STREAM &eth_in,
#pragma HLS INTERFACE ap_none register port=out_idle
#pragma HLS INTERFACE ap_none register port=mode
#pragma HLS INTERFACE ap_none register port=one_over_energy
#pragma HLS INTERFACE ap_none register port=energy_kev
#pragma HLS INTERFACE ap_none register port=nframes
#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=data_collection_state
#pragma HLS PIPELINE II=1 style=flp
@@ -39,8 +41,6 @@ void data_collection_fsm(AXI_STREAM &eth_in,
packet_512_t packet_out;
axis_addr addr;
enum rcv_state_t {RCV_WAIT_FOR_START = 0, RCV_WAIT_FOR_START_LOW = 1, RCV_START = 2, RCV_INIT = 3, RCV_GOOD = 4,
RCV_FLUSH = 5, RCV_LAST = 6, RCV_FLUSH_IDLE = 7, RCV_IGNORE = 8};
static rcv_state_t rcv_state = RCV_WAIT_FOR_START;
#pragma HLS RESET variable=rcv_state
@@ -73,18 +73,18 @@ void data_collection_fsm(AXI_STREAM &eth_in,
out_idle = 0;
packet_out.data = 0;
ACT_REG_MODE(packet_out.data) = mode;
ACT_REG_ONE_OVER_ENERGY(packet_out.data) = one_over_energy;
ACT_REG_ENERGY_KEV_FLOAT(packet_out.data) = energy_kev;
ACT_REG_NFRAMES(packet_out.data) = nframes;
ACT_REG_NMODULES(packet_out.data) = nmodules;
ACT_REG_NSTORAGE_CELLS(packet_out.data) = nstorage_cells + 1;
ACT_REG_NSUMMATION(packet_out.data) = nsummation;
packet_out.user = 0;
packet_out.last = 0;
packet_out.last = 1;
packet_out.dest = 0;
packet_out.id = 1;
data_out << packet_out;
rcv_state = RCV_INIT;
break;
case RCV_INIT:
@@ -138,5 +138,6 @@ void data_collection_fsm(AXI_STREAM &eth_in,
rcv_state = RCV_WAIT_FOR_START;
break;
}
data_collection_state = rcv_state;
}
+4 -3
View File
@@ -36,17 +36,18 @@ void ethernet(AXI_STREAM &eth_in,
if (state == INSPECT_HEADER) {
dest = DEST_IGNORE;
if (fpga_mac_addr != 0) {
if ((fpga_mac_addr != 0) || (packet_in.id == AXI_STREAM_ID_SIMPLIFIED_NETWORK_STACK)) {
ap_uint<48> dest_mac = packet_in.data(47, 0);
ap_uint<48> src_mac = packet_in.data(95, 48);
ap_uint<16> ether_type = get_header_field_16(packet_in.data, 12 * 8);
if ((dest_mac == fpga_mac_addr) && (ether_type == ETHER_IP)) {
if (((dest_mac == fpga_mac_addr) || (packet_in.id == AXI_STREAM_ID_SIMPLIFIED_NETWORK_STACK)) // don't check MAC address for 4x10G
&& (ether_type == ETHER_IP)) {
state = FORWARD;
dest = DEST_IP;
internal_counter++;
} else if ((dest_mac == MAC_BROADCAST) && (ether_type == ETHER_ARP) && (packet_in.last)
&& (packet_in.id == AXI_STREAM_ID_ENABLE_ARP_ICMP)) {
&& (packet_in.id == AXI_STREAM_ID_FULL_NETWORK_STACK)) {
state = FORWARD;
dest = DEST_ARP;
}
+19 -3
View File
@@ -17,7 +17,8 @@ void generate_packet(STREAM_512 &data_out,
ap_uint<64> bunchid,
ap_uint<32> exptime,
ap_uint<64> timestamp,
ap_uint<32> debug) {
ap_uint<32> debug,
ap_uint<1> user = 0) {
#pragma HLS PIPELINE II=130
ap_uint<720> header = 0;
@@ -48,7 +49,7 @@ void generate_packet(STREAM_512 &data_out,
packet.id = 0;
packet.strb = UINT64_MAX;
packet.keep = UINT64_MAX;
packet.user = 0;
packet.user = user;
data_out << packet;
@@ -109,6 +110,21 @@ int frame_generator(STREAM_512 &data_out,
if (modules > MAX_MODULES_FPGA)
return 1;
// send one packet with TUSER = 1, to reset on network cores on the way
generate_packet(data_out,
d_hbm_p0,
d_hbm_p1,
hbm_size_bytes,
0, 0, 0,
src_mac_addr,
dest_mac_addr,
src_ipv4_addr,
dest_ipv4_addr,
bunchid,
exptime,
exptime,
debug, 1);
for (uint32_t f = 0; f < frames; f++) {
ap_uint<1> local_cancel = in_cancel;
if (local_cancel == 1)
@@ -127,7 +143,7 @@ int frame_generator(STREAM_512 &data_out,
bunchid + f,
exptime,
exptime * f,
debug);
debug, 0);
}
}
}
+16 -4
View File
@@ -23,11 +23,15 @@ ap_uint<768> extend_18_to_24(ap_int<576> input) {
void frame_summation(STREAM_576 &data_in, STREAM_768 &data_out,
hls::stream<axis_completion > &s_axis_completion,
hls::stream<axis_completion > &m_axis_completion) {
hls::stream<axis_completion > &m_axis_completion,
volatile ap_uint<1> &idle) {
#pragma HLS INTERFACE axis register both port=data_in
#pragma HLS INTERFACE axis register both port=data_out
#pragma HLS INTERFACE axis register both port=s_axis_completion
#pragma HLS INTERFACE axis register both port=m_axis_completion
#pragma HLS INTERFACE ap_none register port=idle
idle = 1;
ap_uint<24 * 32> memory_0[16384];
#pragma HLS BIND_STORAGE variable=memory_0 type=ram_t2p impl=uram latency=3
@@ -35,9 +39,16 @@ void frame_summation(STREAM_576 &data_in, STREAM_768 &data_out,
packet_576_t packet_in;
packet_768_t packet_out;
data_in >> packet_in;
{
#pragma HLS PROTOCOL fixed
data_in >> packet_in;
ap_wait();
data_out << packet_768_t{.data = packet_in.data, .user = 0, .last = 0};
ap_wait();
idle = 0;
ap_wait();
}
ap_uint<8> sum = ACT_REG_NSUMMATION(packet_in.data); // 0..255
data_out << packet_768_t{.data = packet_in.data, .user = 0, .last = 0};
data_in >> packet_in;
@@ -108,4 +119,5 @@ void frame_summation(STREAM_576 &data_in, STREAM_768 &data_out,
}
m_axis_completion << cmpl;
data_out << packet_768_t{.data = packet_in.data, .user = 1, .last = 0};
}
idle = 1;
}
+7 -2
View File
@@ -25,8 +25,13 @@ void frame_summation_reorder_compl(STREAM_512 &data_in,
}
packet_512_t packet_in;
data_in >> packet_in;
data_out << packet_in;
{
#pragma HLS PROTOCOL fixed
data_in >> packet_in;
ap_wait();
data_out << packet_in;
ap_wait();
}
ap_uint<8> sum = ACT_REG_NSUMMATION(packet_in.data); // 0..255
axis_completion c;
+2 -1
View File
@@ -60,8 +60,9 @@ int test(size_t nframes, int16_t min, int16_t max) {
for (int i = 0; i < nframes; i++)
compl_in << axis_completion{.packet_mask = packet_mask, .frame_number = 100 + i, .packet_count = 128, .last = 0};
compl_in << axis_completion{.last = 1};
ap_uint<1> idle;
frame_summation(input, output, compl_in, compl_out);
frame_summation(input, output, compl_in, compl_out, idle);
if (compl_in.size() != 0) {
std::cout << "compl_in should be empty: " << compl_in.size() << std::endl;
+2 -1
View File
@@ -56,7 +56,8 @@ int test(size_t nframes, int16_t min, int16_t max) {
compl_in << axis_completion{.packet_mask = packet_mask, .frame_number = 100 + i, .packet_count = 128, .last = 0};
compl_in << axis_completion{.last = 1};
frame_summation(input, output, compl_in, compl_out);
ap_uint<1> idle;
frame_summation(input, output, compl_in, compl_out, idle);
if (compl_in.size() != 0) {
std::cout << "compl_in should be empty: " << compl_in.size() << std::endl;
+32 -18
View File
@@ -3,6 +3,8 @@
#ifndef JUNGFRAUJOCH_HLS_JFJOCH_H
#define JUNGFRAUJOCH_HLS_JFJOCH_H
#include "../include/jfjoch_fpga.h"
#include <ap_int.h>
#include <cstdint>
#include <cstring>
@@ -12,10 +14,11 @@
#include <ap_axi_sdata.h>
#include <hls_stream.h>
#else
#define ap_wait()
#include "parallel_stream.h"
#endif
#include "../../common/Definitions.h"
#include "../include/jfjoch_fpga.h"
#define INT18_MAX (131071)
#define INT18_MIN (-131072)
@@ -23,12 +26,13 @@
#define INT24_MAX 8388607
#define INT24_MIN (-8388608)
#define AXI_STREAM_ID_ENABLE_ARP_ICMP 0
#define AXI_STREAM_ID_DISABLE_ARP_ICMP 1
#define AXI_STREAM_ID_FULL_NETWORK_STACK 0 // For 100G provide full network stack - enforce MAC/IPv4 and provide provide ARP/ICMP
#define AXI_STREAM_ID_SIMPLIFIED_NETWORK_STACK 1 // For 4x10G the connection is direct detector-DCU, so no need to enforce MAC/IPv4 and to provide ARP and ICMP
typedef ap_ufixed<16,2, AP_RND_CONV> gainG0_t;
typedef ap_ufixed<16,4, AP_RND_CONV> gainG1_t;
typedef ap_ufixed<16,6, AP_RND_CONV> gainG2_t;
typedef ap_ufixed<16,1, AP_RND_CONV> integration_factor_t;
typedef ap_ufixed<32,12,AP_RND_CONV> one_over_energy_t;
@@ -57,7 +61,7 @@ typedef hls::stream<packet_576_t> STREAM_576;
typedef hls::stream<packet_768_t> STREAM_768;
#define ACT_REG_MODE(x) ((x)(32 , 0)) // 32 bit
#define ACT_REG_ONE_OVER_ENERGY(x) ((x)(63 , 32)) // 32 bit
#define ACT_REG_ENERGY_KEV_FLOAT(x) ((x)(63 , 32)) // 32 bit
#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
@@ -221,7 +225,8 @@ void udp(AXI_STREAM &eth_in,
AXI_STREAM &udp_payload_out,
hls::stream<ap_uint<UDP_METADATA_STREAM_WIDTH> > &udp_metadata_out,
uint64_t& counter,
volatile ap_uint<1> &in_clear_counters);
volatile ap_uint<1> &in_clear_counters,
volatile ap_uint<1> &idle);
void sls_detector(AXI_STREAM &udp_payload_in,
hls::stream<ap_uint<UDP_METADATA_STREAM_WIDTH> > &udp_metadata_in,
@@ -230,7 +235,8 @@ void sls_detector(AXI_STREAM &udp_payload_in,
uint64_t& counter,
uint32_t& counter_eth_error,
uint32_t& counter_len_error,
volatile ap_uint<1> &in_clear_counters);
volatile ap_uint<1> &in_clear_counters,
volatile ap_uint<1> &idle);
// Image modification and analysis cores
@@ -276,8 +282,8 @@ void jf_conversion(STREAM_512 &data_in, STREAM_576 &data_out,
void spot_finder(STREAM_768 &data_in,
STREAM_768 &data_out,
hls::stream<ap_axiu<32,1,1,1>> &strong_pixel_out,
volatile ap_int<16> &in_count_threshold,
volatile ap_uint<8> &in_snr_threshold);
volatile ap_int<32> &in_count_threshold,
volatile ap_uint<32> &in_snr_threshold);
void integration(STREAM_768 &data_in,
STREAM_768 &data_out,
@@ -288,10 +294,14 @@ void integration(STREAM_768 &data_in,
ap_uint<256> *d_hbm_p1,
ap_uint<256> *d_hbm_p2,
ap_uint<256> *d_hbm_p3,
volatile ap_uint<1> &idle,
ap_uint<32> hbm_size_bytes);
// Packet stream handling
enum rcv_state_t {RCV_WAIT_FOR_START = 0, RCV_WAIT_FOR_START_LOW = 1, RCV_START = 2, RCV_INIT = 3, RCV_GOOD = 4,
RCV_FLUSH = 5, RCV_LAST = 6, RCV_FLUSH_IDLE = 7, RCV_IGNORE = 8};
void data_collection_fsm(AXI_STREAM &eth_in,
STREAM_512 &data_out,
hls::stream<axis_addr> &addr_in,
@@ -300,11 +310,12 @@ void data_collection_fsm(AXI_STREAM &eth_in,
volatile ap_uint<1> &in_cancel,
volatile ap_uint<1> &out_idle,
ap_uint<32> mode,
ap_uint<32> one_over_energy,
ap_uint<32> energy_kev,
ap_uint<32> nframes,
ap_uint<5> nmodules,
ap_uint<4> nstorage_cells,
ap_uint<8> nsummation);
ap_uint<8> nsummation,
volatile rcv_state_t &state);
void host_writer(STREAM_512 &data_in,
hls::stream<ap_uint<512>> &adu_histo_in,
@@ -317,7 +328,9 @@ void host_writer(STREAM_512 &data_in,
hls::stream<ap_uint<32> > &m_axis_completion,
const uint64_t *dma_address_table,
volatile uint64_t &packets_processed,
volatile ap_uint<1> &idle);
volatile ap_uint<1> &idle,
volatile ap_uint<1> &in_cancel,
volatile ap_uint<3> &state);
void load_from_hbm(STREAM_512 &data_in,
STREAM_512 &data_out,
@@ -328,6 +341,7 @@ void load_from_hbm(STREAM_512 &data_in,
hls::stream<ap_axiu<256,1,1,1> > &hbm_in_1,
hls::stream<axis_datamover_ctrl> &datamover_0_cmd,
hls::stream<axis_datamover_ctrl> &datamover_1_cmd,
volatile ap_uint<1> &idle,
ap_uint<32> hbm_size_bytes);
void save_to_hbm(STREAM_512 &data_in,
@@ -339,6 +353,7 @@ void save_to_hbm(STREAM_512 &data_in,
hls::stream<ap_axiu<256,1,1,1> > &hbm_out_1,
hls::stream<axis_datamover_ctrl> &datamover_0_cmd,
hls::stream<axis_datamover_ctrl> &datamover_1_cmd,
volatile ap_uint<1> &idle,
ap_uint<32> hbm_size_bytes);
void timer_host(STREAM_512 &data_in,
@@ -363,26 +378,25 @@ int frame_generator(STREAM_512 &data_out,
ap_uint<32> debug,
volatile ap_uint<1> &in_cancel);
int load_calibration(ap_uint<256> *d_hbm_p0,
ap_uint<256> *d_hbm_p1,
ap_uint<8> modules,
ap_uint<5> storage_cells,
const LoadCalibrationConfig &config,
ap_uint<32> hbm_size_bytes,
ap_uint<8> destination,
hls::stream<axis_datamover_ctrl> &datamover_in_cmd,
hls::stream<ap_axiu<512,1,1,1> > &host_memory_in,
const uint64_t *handle_to_dma_address);
const uint64_t *dma_address_table);
void frame_summation(STREAM_576 &data_in, STREAM_768 &data_out,
hls::stream<axis_completion > &s_axis_completion,
hls::stream<axis_completion > &m_axis_completion);
hls::stream<axis_completion > &m_axis_completion,
volatile ap_uint<1> &idle);
void frame_summation_reorder_compl(STREAM_512 &data_in,
STREAM_512 &data_out,
hls::stream<axis_completion > &s_axis_completion,
hls::stream<axis_completion > &m_axis_completion);
void stream_24bit_conv(STREAM_768 &data_in, STREAM_512 &data_out);
void stream_24bit_conv(STREAM_768 &data_in, STREAM_512 &data_out,
volatile ap_uint<1> &idle);
#endif
+93 -32
View File
@@ -1,12 +1,11 @@
// Copyright (2019-2023) Paul Scherrer Institute
#include "hls_jfjoch.h"
#include "../host_library/DeviceOutput.h"
#define o(field) offsetof(ModuleStatistics, field)
#define sf(msg, field, s) msg(o(field)*8 + s - 1, o(field)*8)
inline ap_uint<512> fill_module_info(axis_completion &cmpl) {
inline ap_uint<512> fill_module_info(axis_completion &cmpl, ap_uint<32> sat_pxl, ap_uint<32> err_pxl) {
ap_uint<512> msg = 0;
sf(msg, frame_number, 64) = cmpl.frame_number;
sf(msg, timestamp, 64) = cmpl.timestamp;
@@ -16,6 +15,8 @@ inline ap_uint<512> fill_module_info(axis_completion &cmpl) {
sf(msg, pedestal, 32) = cmpl.pedestal;
sf(msg, packet_count, 32) = cmpl.packet_count;
sf(msg, module_number, 32) = cmpl.module;
sf(msg, saturated_pixels, 32) = sat_pxl;
sf(msg, err_pixels, 32) = err_pxl;
return msg;
}
@@ -45,7 +46,9 @@ void host_writer(STREAM_512 &data_in,
hls::stream<ap_uint<32> > &m_axis_completion,
const uint64_t *dma_address_table,
volatile uint64_t &packets_processed,
volatile ap_uint<1> &idle) {
volatile ap_uint<1> &idle,
volatile ap_uint<1> &in_cancel,
volatile ap_uint<3> &state) {
#pragma HLS INTERFACE ap_ctrl_none port=return
#pragma HLS INTERFACE register both axis port=data_in
#pragma HLS INTERFACE register both axis port=adu_histo_in
@@ -58,18 +61,32 @@ void host_writer(STREAM_512 &data_in,
#pragma HLS INTERFACE register both axis port=s_axis_work_request
#pragma HLS INTERFACE register ap_vld port=packets_processed
#pragma HLS INTERFACE register ap_none port=idle
#pragma HLS INTERFACE register ap_none port=in_cancel
#pragma HLS INTERFACE register ap_none port=state
#pragma HLS INTERFACE mode=m_axi port=dma_address_table bundle=dma_address_table depth=65536 offset=off \
max_read_burst_length=2 max_write_burst_length=2 latency=10 num_write_outstanding=1 num_read_outstanding=1
idle = 1;
state = 0;
ap_uint<16> req_handle;
ap_uint<64> req_host_offset;
while (data_in.empty()) {
if (!s_axis_work_request.empty()) {
#pragma HLS PIPELINE II=1
read_request(s_axis_work_request, req_handle);
write_completion(m_axis_completion, req_handle, DATA_COLLECTION_ID_PURGE);
}
}
packet_512_t packet;
data_in >> packet;
{
#pragma HLS PROTOCOL fixed
data_in >> packet;
ap_wait();
}
ap_uint<32> data_collection_mode = ACT_REG_MODE(packet.data);
ap_uint<32> data_collection_id = data_collection_mode(31, 16);
ap_uint<1> mode_32bit = (data_collection_mode & MODE_32BIT) ? 1 : 0;
@@ -80,11 +97,37 @@ void host_writer(STREAM_512 &data_in,
idle = 0;
size_t pixel_depth;
if (mode_32bit)
pixel_depth = 4;
else
pixel_depth = 2;
axis_completion cmpl;
s_axis_completion >> cmpl;
state = 1;
while (!cmpl.last) {
read_request(s_axis_work_request, req_handle);
req_host_offset = dma_address_table[req_handle];
ap_uint<1> send_images = 1;
while (s_axis_work_request.empty() && !in_cancel.read()) {
#pragma HLS PIPELINE II=1
ap_wait();
}
if (s_axis_work_request.empty()) {
send_images = 0;
state = 2;
} else
state = 3;
// Either send_images == 0 (so collection can proceed without writing to host mem)
// or s_axis_work_request is not empty (so collection can proceed with writing to host mem)
if (send_images) {
read_request(s_axis_work_request, req_handle);
req_host_offset = dma_address_table[req_handle];
send_images = (req_host_offset != 0);
}
packet_512_t packet_out;
packet_out.strb = UINT64_MAX;
packet_out.keep = UINT64_MAX;
@@ -93,20 +136,16 @@ void host_writer(STREAM_512 &data_in,
packet_out.id = 0;
packet_out.last = 0;
size_t pixel_depth;
if (mode_32bit)
pixel_depth = 4;
else
pixel_depth = 2;
setup_datamover(datamover_out_cmd, req_host_offset, RAW_MODULE_SIZE * pixel_depth);
setup_datamover(datamover_out_cmd, req_host_offset + offsetof(DeviceOutput, spot_finding_result),
RAW_MODULE_SIZE * sizeof(uint16_t) / 16 + 64);
setup_datamover(datamover_out_cmd, req_host_offset + offsetof(DeviceOutput, integration_result),
(FPGA_INTEGRATION_BIN_COUNT / 8) * 64);
setup_datamover(datamover_out_cmd, req_host_offset + offsetof(DeviceOutput, adu_histogram),
ADU_HISTO_BIN_COUNT / 16 * 64);
setup_datamover(datamover_out_cmd, req_host_offset + offsetof(DeviceOutput, module_statistics), 2*64);
if (send_images) {
setup_datamover(datamover_out_cmd, req_host_offset, RAW_MODULE_SIZE * pixel_depth);
setup_datamover(datamover_out_cmd, req_host_offset + offsetof(DeviceOutput, spot_finding_result),
RAW_MODULE_SIZE * sizeof(uint16_t) / 16 + 64);
setup_datamover(datamover_out_cmd, req_host_offset + offsetof(DeviceOutput, integration_result),
(FPGA_INTEGRATION_BIN_COUNT / 8) * 64);
setup_datamover(datamover_out_cmd, req_host_offset + offsetof(DeviceOutput, adu_histogram),
ADU_HISTO_BIN_COUNT / 16 * 64);
setup_datamover(datamover_out_cmd, req_host_offset + offsetof(DeviceOutput, module_statistics), 2 * 64);
}
if (pixel_depth == 2) {
for (int i = 0; i < RAW_MODULE_SIZE * 2 / 64; i++) {
@@ -117,7 +156,8 @@ void host_writer(STREAM_512 &data_in,
packet_out.last = 1;
else
packet_out.last = 0;
host_memory_out << packet_out;
if (send_images)
host_memory_out << packet_out;
}
} else {
for (int i = 0; i < RAW_MODULE_SIZE * 4 / 64; i++) {
@@ -128,7 +168,8 @@ void host_writer(STREAM_512 &data_in,
packet_out.last = 1;
else
packet_out.last = 0;
host_memory_out << packet_out;
if (send_images)
host_memory_out << packet_out;
}
}
@@ -139,7 +180,8 @@ void host_writer(STREAM_512 &data_in,
#pragma HLS PIPELINE II=1
spot_finder_in >> packet_out.data;
packet_out.last = (i == RAW_MODULE_SIZE * sizeof(uint16_t) / (64 * 16) + 1 - 1);
host_memory_out << packet_out;
if (send_images)
host_memory_out << packet_out;
}
// 128 transfers x 512-bit
@@ -147,7 +189,8 @@ void host_writer(STREAM_512 &data_in,
#pragma HLS PIPELINE II=1
integration_in >> packet_out.data;
packet_out.last = (i == FPGA_INTEGRATION_BIN_COUNT / 8 - 1);
host_memory_out << packet_out;
if (send_images)
host_memory_out << packet_out;
}
// 128 transfers x 512-bit
@@ -156,25 +199,43 @@ void host_writer(STREAM_512 &data_in,
ap_uint<512> tmp;
adu_histo_in >> packet_out.data;
packet_out.last = (i == ADU_HISTO_BIN_COUNT / 16 - 1);
host_memory_out << packet_out;
if (send_images)
host_memory_out << packet_out;
}
packet_out.data = fill_module_info(cmpl);
if (send_images)
state = 5;
else
state = 4;
adu_histo_in >> packet_out.data;
packet_out.data = fill_module_info(cmpl, packet_out.data(31,0), packet_out.data(63,32));
packet_out.last = 0;
host_memory_out << packet_out;
if (send_images)
host_memory_out << packet_out;
packet_out.data = cmpl.packet_mask;
packet_out.last = 1;
host_memory_out << packet_out;
write_completion(m_axis_completion, req_handle, data_collection_id);
internal_packets_processed += cmpl.packet_count;
packets_processed = internal_packets_processed;
if (send_images)
host_memory_out << packet_out;
if (send_images) {
write_completion(m_axis_completion, req_handle, data_collection_id);
internal_packets_processed += cmpl.packet_count;
packets_processed = internal_packets_processed;
}
state = 6;
s_axis_completion >> cmpl;
state = 7;
}
data_in >> packet;
write_completion(m_axis_completion, HANDLE_END, data_collection_id);
idle = 1;
}
+16 -4
View File
@@ -11,6 +11,7 @@ void integration(STREAM_768 &data_in,
ap_uint<256> *d_hbm_p1,
ap_uint<256> *d_hbm_p2,
ap_uint<256> *d_hbm_p3,
volatile ap_uint<1> &idle,
ap_uint<32> hbm_size_bytes) {
#pragma HLS INTERFACE register both axis port=data_in
#pragma HLS INTERFACE register both axis port=data_out
@@ -18,6 +19,8 @@ void integration(STREAM_768 &data_in,
#pragma HLS INTERFACE register both axis port=m_axis_completion
#pragma HLS INTERFACE register both axis port=s_axis_completion
#pragma HLS INTERFACE register ap_none port=hbm_size_bytes
#pragma HLS INTERFACE register ap_none port=idle
#pragma HLS INTERFACE m_axi port=d_hbm_p0 bundle=d_hbm_p0 depth=16384 offset=off \
max_read_burst_length=16 max_write_burst_length=2 latency=120 num_write_outstanding=2 num_read_outstanding=8
#pragma HLS INTERFACE m_axi port=d_hbm_p1 bundle=d_hbm_p1 depth=16384 offset=off \
@@ -27,6 +30,8 @@ void integration(STREAM_768 &data_in,
#pragma HLS INTERFACE m_axi port=d_hbm_p3 bundle=d_hbm_p3 depth=16384 offset=off \
max_read_burst_length=16 max_write_burst_length=2 latency=120 num_write_outstanding=2 num_read_outstanding=8
idle = 1;
ap_fixed<50,34, AP_RND_CONV> sum[64][FPGA_INTEGRATION_BIN_COUNT];
// log2(32768*512*1024/64) = 32 + sign 1 bit
#pragma HLS BIND_STORAGE variable=sum type=ram_t2p impl=bram
@@ -46,14 +51,20 @@ void integration(STREAM_768 &data_in,
ap_int<24> in_val[32];
ap_uint<16> in_bin[32];
ap_ufixed<16,1, AP_RND_CONV> in_coeff[32];
integration_factor_t in_coeff[32];
ap_uint<256> bins_0, bins_1, coeff_0, coeff_1;
packet_768_t packet_in;
data_in >> packet_in;
data_out << packet_in;
{
#pragma HLS PROTOCOL fixed
data_in >> packet_in;
ap_wait();
data_out << packet_in;
ap_wait();
idle = 0;
ap_wait();
}
ap_uint<32> offset_hbm_0 = 16 * hbm_size_bytes / 32;
ap_uint<32> offset_hbm_1 = 17 * hbm_size_bytes / 32;
ap_uint<32> offset_hbm_2 = 18 * hbm_size_bytes / 32;
@@ -123,4 +134,5 @@ void integration(STREAM_768 &data_in,
data_in >> packet_in;
data_out << packet_in;
idle = 1;
}
+3 -1
View File
@@ -30,7 +30,9 @@ int main() {
compl_in << axis_completion{.last = 1};
input << packet_768_t{.user = 1};
integration(input, output, integration_result, compl_in, compl_out, hbm_0, hbm_1, hbm_2, hbm_3, 0);
ap_uint<1> idle;
integration(input, output, integration_result, compl_in, compl_out, hbm_0, hbm_1, hbm_2, hbm_3, idle, 0);
if (input.size() != 0)
ret = 1;
+27 -26
View File
@@ -5,9 +5,9 @@
#include "ip_header_checksum.h"
void ipv4(AXI_STREAM &eth_in,
AXI_STREAM &udp_out,
AXI_STREAM &icmp_out,
ap_uint<32> fpga_ipv4_addr) {
AXI_STREAM &udp_out,
AXI_STREAM &icmp_out,
ap_uint<32> fpga_ipv4_addr) {
#pragma HLS INTERFACE ap_ctrl_none port=return
#pragma HLS INTERFACE axis register both port=eth_in
#pragma HLS INTERFACE axis register both port=udp_out
@@ -19,46 +19,47 @@ void ipv4(AXI_STREAM &eth_in,
enum ipv4_state {INSPECT_HEADER, FORWARD, DISCARD};
static ipv4_state state = INSPECT_HEADER;
static ipv4_dest dest;
static uint64_t internal_counter = 0;
packet_512_t packet_in = eth_in.read();
if (state == INSPECT_HEADER) {
dest = DEST_IGNORE;
packet_512_t packet_in;
if (eth_in.read_nb(packet_in)) {
if (state == INSPECT_HEADER) {
dest = DEST_IGNORE;
ap_uint<4> ip_version = packet_in.data(eth_payload_pos + 8 - 1, eth_payload_pos + 4);
ap_uint<8> ipv4_protocol = packet_in.data(eth_payload_pos + 80 - 1, eth_payload_pos + 72);
ap_uint<32> ipv4_dest_ip = packet_in.data(eth_payload_pos + 128 + 31, eth_payload_pos + 128);
ap_uint<16> ipv4_header_checksum_check = computeCheckSum20B(packet_in.data(eth_payload_pos + 159, eth_payload_pos));
ap_uint<16> ipv4_header_checksum_check = computeCheckSum20B(
packet_in.data(eth_payload_pos + 159, eth_payload_pos));
if ((ip_version == 4) && (ipv4_dest_ip == fpga_ipv4_addr) && (ipv4_header_checksum_check == 0)) {
if ((ip_version == 4)
&& ((ipv4_dest_ip == fpga_ipv4_addr) ||
(packet_in.id == AXI_STREAM_ID_SIMPLIFIED_NETWORK_STACK)) // don't check IPv4 address for 4x10G
&& (ipv4_header_checksum_check == 0)) {
// IP is version 4 + IP address is correct + checksum is OK
// Possibly the conditions can be relaxed for broadcast ICMP
if (ipv4_protocol == PROTOCOL_UDP) {
state = FORWARD;
dest = DEST_UDP;
} else if ((ipv4_protocol == PROTOCOL_ICMP) && (packet_in.id == AXI_STREAM_ID_ENABLE_ARP_ICMP)) {
} else if ((ipv4_protocol == PROTOCOL_ICMP) && (packet_in.id == AXI_STREAM_ID_FULL_NETWORK_STACK)) {
state = FORWARD;
dest = DEST_ICMP;
}
}
}
}
switch (dest) {
case DEST_UDP:
udp_out.write(packet_in);
break;
case DEST_ICMP:
icmp_out.write(packet_in);
break;
default:
break;
}
switch (dest) {
case DEST_UDP:
udp_out.write(packet_in);
break;
case DEST_ICMP:
icmp_out.write(packet_in);
break;
default:
break;
}
if (packet_in.last) {
state = INSPECT_HEADER;
internal_counter++;
if (packet_in.last)
state = INSPECT_HEADER;
}
}
+33 -15
View File
@@ -1,10 +1,15 @@
// Copyright (2019-2023) Paul Scherrer Institute
#ifndef JFJOCH_HLS_NOSYNTH
#include <hls_math.h>
#else
namespace hls {
inline float recip(float f) {return 1.0f/f;}
}
#endif
#include "hls_jfjoch.h"
#define HBM_BURST 16
// HBM and in-memory order:
// (HBM) p0, p1 - gain G0
// (HBM) p2, p3 - gain G1
@@ -21,6 +26,7 @@ ap_uint<576> convert(ap_uint<512> data_in,
ap_uint<256> packed_pedeG1_1, ap_uint<256> packed_pedeG1_2,
ap_uint<256> packed_pedeG2_1, ap_uint<256> packed_pedeG2_2,
ap_uint<1> save_raw,
ap_uint<1> fixed_g1,
one_over_energy_t one_over_energy_in_keV)
{
#pragma HLS PIPELINE
@@ -51,14 +57,17 @@ ap_uint<576> convert(ap_uint<512> data_in,
for (int i = 0; i < 32; i++) {
ap_uint<2> gain = in_val[i](15,14);
if (save_raw) for (int j = 0; j < 16; j++) out_val[i][j] = in_val[i][j];
else if (gainG0[i] == 0) out_val[i] = INT18_MIN; // if G0 gain factor is zero - mask pixel
else if (in_val[i] == 0xc000) out_val[i] = INT18_MAX; // can saturate G2 - overload
else if ((gain == 0) && (gainG0[i] == 0)) out_val[i] = INT18_MIN; // if G0 gain factor is zero - mask pixel
else if ((gain == 1) && (gainG1[i] == 0)) out_val[i] = INT18_MIN; // if G1 gain factor is zero - mask pixel
else if ((gain == 3) && (gainG2[i] == 0)) out_val[i] = INT18_MIN; // if G2 gain factor is zero - mask pixel
else if (in_val[i] == 0xc000) out_val[i] = fixed_g1 ? INT18_MIN : INT18_MAX; // can saturate G2 - overload (but not when fixed G1)
else if (in_val[i] == 0xffff) out_val[i] = INT18_MIN; //error
else if (in_val[i] == 0x4000) out_val[i] = INT18_MIN; //cannot saturate G1 - error
else if (in_val[i] == 0x4000) out_val[i] = fixed_g1 ? INT18_MAX : INT18_MIN; // Cannot saturate G1 - error (but it is possible in fixed G1 mode)
else if (gain == 2) out_val[i] = INT18_MIN; // invalid gain
else if ((pedeG0[i] > 16383) && (gain == 0)) out_val[i] = INT18_MIN;
else if ((pedeG1[i] > 16383) && (gain == 1)) out_val[i] = INT18_MIN;
else if ((pedeG2[i] > 16383) && (gain == 3)) out_val[i] = INT18_MIN;
else if ((gain != 1) && fixed_g1) out_val[i] = INT18_MIN; // With fixed gain G1, don't expected anything else!
else {
ap_fixed<18,16, AP_RND_CONV> val_diff = 0;
ap_ufixed<25,6,AP_RND_CONV> val_gain = 0;
@@ -67,7 +76,10 @@ ap_uint<576> convert(ap_uint<512> data_in,
val_diff = adu - pedeG0[i];
val_gain = ap_ufixed<25,6,AP_RND_CONV>(gainG0[i]) / 32;
} else if (gain == 1) {
val_diff = pedeG1[i] - adu;
if (fixed_g1)
val_diff = adu - pedeG1[i];
else
val_diff = pedeG1[i] - adu;
val_gain = gainG1[i];
} else {
val_diff = pedeG2[i] - adu;
@@ -132,19 +144,24 @@ void jf_conversion(STREAM_512 &data_in, STREAM_576 &data_out,
packet_512_t packet_in;
packet_576_t packet_out;
{
#pragma HLS PROTOCOL fixed
data_in >> packet_in;
ap_wait();
packet_out.data = packet_in.data;
packet_out.last = packet_in.last;
packet_out.user = packet_in.user;
data_out << packet_out;
ap_wait();
}
data_in >> packet_in;
packet_out.data = packet_in.data;
packet_out.last = packet_in.last;
packet_out.user = packet_in.user;
data_out << packet_out;
float_uint32 in_one_over_energy;
float_uint32 in_energy_kev;
ap_uint<64> mode = ACT_REG_MODE(packet_in.data);
ap_uint<1> conversion = (mode & MODE_CONV) ? 1 : 0;
ap_uint<1> fixed_g1 = (mode & MODE_FIXG1) ? 1 : 0;
ap_uint<6> modules = ACT_REG_NMODULES(packet_in.data) + 1;
in_one_over_energy.u = ACT_REG_ONE_OVER_ENERGY(packet_in.data);
in_energy_kev.u = ACT_REG_ENERGY_KEV_FLOAT(packet_in.data);
ap_uint<5> storage_cells = ACT_REG_NSTORAGE_CELLS(packet_in.data);
ap_uint<32> offset_hbm_0 = 0 * hbm_size_bytes / 32;
@@ -160,7 +177,7 @@ void jf_conversion(STREAM_512 &data_in, STREAM_576 &data_out,
ap_uint<32> offset_hbm_10 = 10 * hbm_size_bytes / 32;
ap_uint<32> offset_hbm_11 = 11 * hbm_size_bytes / 32;
one_over_energy_t one_over_energy = in_one_over_energy.f;
one_over_energy_t one_over_energy = hls::recip(in_energy_kev.f);
if (conversion) {
axis_completion cmpl;
@@ -216,6 +233,7 @@ void jf_conversion(STREAM_512 &data_in, STREAM_576 &data_out,
packed_pedeG1_1, packed_pedeG1_2,
packed_pedeG2_1, packed_pedeG2_2,
packet_in.id[0],
fixed_g1,
one_over_energy);
packet_out.last = packet_in.last;
packet_out.user = packet_in.user;
+143 -92
View File
@@ -1,46 +1,97 @@
// Copyright (2019-2023) Paul Scherrer Institute
#ifndef JFJOCH_HLS_NOSYNTH
#include <hls_math.h>
#else
#include <cmath>
namespace hls {
inline bool isfinite(float f) {return std::isfinite(f);}
}
#endif
#include "hls_jfjoch.h"
// Loads calibration from host memory based on 64-bit memory addresses loaded in in_mem_location
// Expected structure in in_mem_location array:
//
// * gain factors for module m at location: 2 + gain level * NMODULES + m
// * pedestal factors for module m and storage cell s at location: 2 + 3 * NMODULES + (gain level * 16 + s ) * NMODULES + m
#define o(field) offsetof(ModuleStatistics, field)
#define sf(msg, field, s) msg(o(field)*8 + s - 1, o(field)*8)
void read_config(hls::stream<ap_axiu<512,1,1,1> > &host_memory_in,
ap_uint<32> &destination,
ap_uint<16> &module_id) {
#pragma HLS INLINE OFF
ap_axiu<512, 1, 1, 1> data_packet;
host_memory_in >> data_packet;
module_id = sf(data_packet.data, module_number, 32);
destination = sf(data_packet.data, load_calibration_destination, 32);
}
void read_module(ap_uint<256> *d_hbm_p0,
ap_uint<256> *d_hbm_p1,
hls::stream<ap_axiu<512,1,1,1> > &host_memory_in,
size_t offset_hbm_0,
size_t offset_hbm_1) {
ap_uint<256> *d_hbm_p1,
hls::stream<ap_axiu<512,1,1,1> > &host_memory_in,
size_t offset_hbm_0,
size_t offset_hbm_1) {
#pragma HLS INLINE OFF
for (int i = 0; i < RAW_MODULE_SIZE * sizeof(int16_t) / 64; i++) {
for (int i = 0; i < RAW_MODULE_SIZE * sizeof(int16_t) / 64; i++) {
#pragma HLS PIPELINE II=1
ap_axiu<512, 1, 1, 1> data_packet;
host_memory_in >> data_packet;
ap_axiu<512, 1, 1, 1> data_packet;
host_memory_in >> data_packet;
d_hbm_p0[offset_hbm_0 + i] = data_packet.data(255, 0);
d_hbm_p1[offset_hbm_1 + i] = data_packet.data(511, 256);
}
d_hbm_p0[offset_hbm_0 + i] = data_packet.data(255, 0);
d_hbm_p1[offset_hbm_1 + i] = data_packet.data(511, 256);
}
}
template <class T, int MULT> ap_uint<256> convert(const ap_uint<512> &in) {
//#pragma HLS INLINE
ap_uint<256> tmp;
for (int j = 0; j < 16; j++) {
float_uint32 conv{};
conv.u = in(j * 32 + 31, j * 32);
float x = conv.f * MULT;
T g;
if (!hls::isfinite(x) || (x < 0.0))
g = 0;
else
g = static_cast<T>(x);
for (int k = 0; k < 16; k++)
tmp[j * 16 + k] = g[k];
}
return tmp;
}
template <class T, int MULT = 1>
void read_module_float(ap_uint<256> *d_hbm_p0,
ap_uint<256> *d_hbm_p1,
hls::stream<ap_axiu<512,1,1,1> > &host_memory_in,
size_t offset_hbm_0,
size_t offset_hbm_1) {
#pragma HLS INLINE OFF
for (int i = 0; i < RAW_MODULE_SIZE * sizeof(int16_t) / 64; i++) {
#pragma HLS PIPELINE II=2
ap_axiu<512, 1, 1, 1> data_packet;
ap_uint<256> tmp;
host_memory_in >> data_packet;
d_hbm_p0[offset_hbm_0 + i] = convert<T, MULT>(data_packet.data);
host_memory_in >> data_packet;
d_hbm_p1[offset_hbm_1 + i] = convert<T, MULT>(data_packet.data);
}
}
int load_calibration(ap_uint<256> *d_hbm_p0,
ap_uint<256> *d_hbm_p1,
ap_uint<8> modules,
ap_uint<5> storage_cells,
ap_uint<32> hbm_size_bytes,
ap_uint<8> destination,
hls::stream<axis_datamover_ctrl> &datamover_in_cmd,
hls::stream<ap_axiu<512,1,1,1> > &host_memory_in,
const uint64_t *dma_address_table) {
ap_uint<256> *d_hbm_p1,
const LoadCalibrationConfig &config,
ap_uint<32> hbm_size_bytes,
hls::stream<axis_datamover_ctrl> &datamover_in_cmd,
hls::stream<ap_axiu<512,1,1,1> > &host_memory_in,
const uint64_t *dma_address_table) {
#pragma HLS INTERFACE mode=s_axilite port=return
#pragma HLS INTERFACE register both axis port=datamover_in_cmd
#pragma HLS INTERFACE register both axis port=host_memory_in
#pragma HLS INTERFACE mode=s_axilite port=modules
#pragma HLS INTERFACE mode=s_axilite port=storage_cells
#pragma HLS INTERFACE mode=s_axilite port=destination
#pragma HLS INTERFACE mode=s_axilite port=config
#pragma HLS INTERFACE mode=ap_none port=hbm_size_bytes
#pragma HLS INTERFACE mode=m_axi port=d_hbm_p0 bundle=d_hbm_p0 depth=512 offset=off \
@@ -50,78 +101,78 @@ int load_calibration(ap_uint<256> *d_hbm_p0,
#pragma HLS INTERFACE mode=m_axi port=dma_address_table bundle=dma_address_table depth=65536 offset=off \
max_read_burst_length=2 max_write_burst_length=2 latency=10 num_write_outstanding=1 num_read_outstanding=1
if ((modules == 0) || (modules > MAX_MODULES_FPGA))
return 1;
uint64_t mem_addr = dma_address_table[config.handle];
if (mem_addr == 0)
return LOAD_CALIBRATION_ERR_HOST_ADDR;
if (destination == LOAD_CALIBRATION_DEST_CALIB) {
if ((storage_cells == 0) || (storage_cells > 16))
return 1;
setup_datamover(datamover_in_cmd, mem_addr + offsetof(DeviceOutput, module_statistics), 64);
ap_uint<16> module_id;
ap_uint<32> destination;
read_config(host_memory_in, destination, module_id);
for (int i = 0; i < 3 * (modules + storage_cells * modules); i++) {
if (dma_address_table[i] == 0)
return 2;
}
if (module_id > 2 * hbm_size_bytes / (RAW_MODULE_SIZE * sizeof(int16_t)))
return LOAD_CALIBRATION_ERR_MODULE;
for (int i = 0; i < 3 * (modules + storage_cells * modules); i++)
setup_datamover(datamover_in_cmd, dma_address_table[i], RAW_MODULE_SIZE * sizeof(int16_t));
size_t offset_hbm_0;
size_t offset_hbm_1;
for (int c = 0; c < 3; c++) {
for (int m = 0; m < modules; m++) {
#pragma HLS PIPELINE OFF
size_t offset_hbm_0 = (2 * c) * hbm_size_bytes / 32 + m * RAW_MODULE_SIZE * sizeof(int16_t) / 64;
size_t offset_hbm_1 = (2 * c + 1) * hbm_size_bytes / 32 + m * RAW_MODULE_SIZE * sizeof(int16_t) / 64;
read_module(d_hbm_p0, d_hbm_p1, host_memory_in, offset_hbm_0, offset_hbm_1);
}
}
for (int c = 0; c < 3; c++) {
for (int m = 0; m < modules * storage_cells; m++) {
#pragma HLS PIPELINE OFF
size_t offset_hbm_0 = (6 + 2 * c) * hbm_size_bytes / 32 + m * RAW_MODULE_SIZE * sizeof(int16_t) / 64;
size_t offset_hbm_1 =
(6 + 2 * c + 1) * hbm_size_bytes / 32 + m * RAW_MODULE_SIZE * sizeof(int16_t) / 64;
read_module(d_hbm_p0, d_hbm_p1, host_memory_in, offset_hbm_0, offset_hbm_1);
}
}
} else if (destination == LOAD_CALIBRATION_DEST_INTEGRATION) {
// load maps
for (int i = 0; i < 2 * modules; i++) {
if (dma_address_table[i] == 0)
return 2;
}
for (int i = 0; i < 2 * modules; i++)
setup_datamover(datamover_in_cmd, dma_address_table[i], RAW_MODULE_SIZE * sizeof(int16_t));
for (int m = 0; m < modules; m++) {
#pragma HLS PIPELINE OFF
size_t offset_hbm_0 = 16 * hbm_size_bytes / 32 + m * RAW_MODULE_SIZE * sizeof(int16_t) / 64;
size_t offset_hbm_1 = 17 * hbm_size_bytes / 32 + m * RAW_MODULE_SIZE * sizeof(int16_t) / 64;
switch (destination) {
case LOAD_CALIBRATION_DEST_GAIN_G0:
setup_datamover(datamover_in_cmd, mem_addr, RAW_MODULE_SIZE * sizeof(float));
offset_hbm_0 = 0 * hbm_size_bytes / 32 + module_id * RAW_MODULE_SIZE * sizeof(int16_t) / 64;
offset_hbm_1 = 1 * hbm_size_bytes / 32 + module_id * RAW_MODULE_SIZE * sizeof(int16_t) / 64;
read_module_float<gainG0_t, GAIN_G0_MULTIPLIER>(d_hbm_p0, d_hbm_p1, host_memory_in, offset_hbm_0, offset_hbm_1);
break;
case LOAD_CALIBRATION_DEST_GAIN_G1:
setup_datamover(datamover_in_cmd, mem_addr, RAW_MODULE_SIZE * sizeof(float));
offset_hbm_0 = 2 * hbm_size_bytes / 32 + module_id * RAW_MODULE_SIZE * sizeof(int16_t) / 64;
offset_hbm_1 = 3 * hbm_size_bytes / 32 + module_id * RAW_MODULE_SIZE * sizeof(int16_t) / 64;
read_module_float<gainG1_t, GAIN_G1_MULTIPLIER>(d_hbm_p0, d_hbm_p1, host_memory_in, offset_hbm_0, offset_hbm_1);
break;
case LOAD_CALIBRATION_DEST_GAIN_G2:
setup_datamover(datamover_in_cmd, mem_addr, RAW_MODULE_SIZE * sizeof(float));
offset_hbm_0 = 4 * hbm_size_bytes / 32 + module_id * RAW_MODULE_SIZE * sizeof(int16_t) / 64;
offset_hbm_1 = 5 * hbm_size_bytes / 32 + module_id * RAW_MODULE_SIZE * sizeof(int16_t) / 64;
read_module_float<gainG2_t, GAIN_G2_MULTIPLIER>(d_hbm_p0, d_hbm_p1, host_memory_in, offset_hbm_0, offset_hbm_1);
break;
case LOAD_CALIBRATION_DEST_PEDESTAL_G0:
setup_datamover(datamover_in_cmd, mem_addr, RAW_MODULE_SIZE * sizeof(int16_t));
offset_hbm_0 = 6 * hbm_size_bytes / 32 + module_id * RAW_MODULE_SIZE * sizeof(int16_t) / 64;
offset_hbm_1 = 7 * hbm_size_bytes / 32 + module_id * RAW_MODULE_SIZE * sizeof(int16_t) / 64;
read_module(d_hbm_p0, d_hbm_p1, host_memory_in, offset_hbm_0, offset_hbm_1);
}
// load weights
for (int m = 0; m < modules; m++) {
#pragma HLS PIPELINE OFF
size_t offset_hbm_0 = 18 * hbm_size_bytes / 32 + m * RAW_MODULE_SIZE * sizeof(int16_t) / 64;
size_t offset_hbm_1 = 19 * hbm_size_bytes / 32 + m * RAW_MODULE_SIZE * sizeof(int16_t) / 64;
break;
case LOAD_CALIBRATION_DEST_PEDESTAL_G1:
setup_datamover(datamover_in_cmd, mem_addr, RAW_MODULE_SIZE * sizeof(int16_t));
offset_hbm_0 = 8 * hbm_size_bytes / 32 + module_id * RAW_MODULE_SIZE * sizeof(int16_t) / 64;
offset_hbm_1 = 9 * hbm_size_bytes / 32 + module_id * RAW_MODULE_SIZE * sizeof(int16_t) / 64;
read_module(d_hbm_p0, d_hbm_p1, host_memory_in, offset_hbm_0, offset_hbm_1);
}
} else if (destination == LOAD_CALIBRATION_DEST_FRAME_GEN) {
for (int i = 0; i < modules; i++) {
if (dma_address_table[i] == 0)
return 2;
}
for (int i = 0; i < modules; i++)
setup_datamover(datamover_in_cmd, dma_address_table[i], RAW_MODULE_SIZE * sizeof(int16_t));
for (int m = 0; m < modules; m++) {
#pragma HLS PIPELINE OFF
size_t offset_hbm_0 = 20 * hbm_size_bytes / 32 + m * RAW_MODULE_SIZE * sizeof(int16_t) / 64;
size_t offset_hbm_1 = 21 * hbm_size_bytes / 32 + m * RAW_MODULE_SIZE * sizeof(int16_t) / 64;
break;
case LOAD_CALIBRATION_DEST_PEDESTAL_G2:
setup_datamover(datamover_in_cmd, mem_addr, RAW_MODULE_SIZE * sizeof(int16_t));
offset_hbm_0 = 10 * hbm_size_bytes / 32 + module_id * RAW_MODULE_SIZE * sizeof(int16_t) / 64;
offset_hbm_1 = 11 * hbm_size_bytes / 32 + module_id * RAW_MODULE_SIZE * sizeof(int16_t) / 64;
read_module(d_hbm_p0, d_hbm_p1, host_memory_in, offset_hbm_0, offset_hbm_1);
}
break;
case LOAD_CALIBRATION_DEST_INTEGRATION_MAP:
setup_datamover(datamover_in_cmd, mem_addr, RAW_MODULE_SIZE * sizeof(int16_t));
offset_hbm_0 = 16 * hbm_size_bytes / 32 + module_id * RAW_MODULE_SIZE * sizeof(int16_t) / 64;
offset_hbm_1 = 17 * hbm_size_bytes / 32 + module_id * RAW_MODULE_SIZE * sizeof(int16_t) / 64;
read_module(d_hbm_p0, d_hbm_p1, host_memory_in, offset_hbm_0, offset_hbm_1);
break;
case LOAD_CALIBRATION_DEST_INTEGRATION_WEIGHTS:
setup_datamover(datamover_in_cmd, mem_addr, RAW_MODULE_SIZE * sizeof(float));
offset_hbm_0 = 18 * hbm_size_bytes / 32 + module_id * RAW_MODULE_SIZE * sizeof(int16_t) / 64;
offset_hbm_1 = 19 * hbm_size_bytes / 32 + module_id * RAW_MODULE_SIZE * sizeof(int16_t) / 64;
read_module_float<integration_factor_t>(d_hbm_p0, d_hbm_p1, host_memory_in, offset_hbm_0, offset_hbm_1);
break;
case LOAD_CALIBRATION_DEST_FRAME_GEN:
setup_datamover(datamover_in_cmd, mem_addr, RAW_MODULE_SIZE * sizeof(int16_t));
offset_hbm_0 = 20 * hbm_size_bytes / 32 + module_id * RAW_MODULE_SIZE * sizeof(int16_t) / 64;
offset_hbm_1 = 21 * hbm_size_bytes / 32 + module_id * RAW_MODULE_SIZE * sizeof(int16_t) / 64;
read_module(d_hbm_p0, d_hbm_p1, host_memory_in, offset_hbm_0, offset_hbm_1);
break;
default:
return LOAD_CALIBRATION_ERR_DEST;
}
return 0;
return LOAD_CALIBRATION_OK;
}
+15 -3
View File
@@ -11,6 +11,7 @@ void load_from_hbm(STREAM_512 &data_in,
hls::stream<ap_axiu<256,1,1,1> > &hbm_in_1,
hls::stream<axis_datamover_ctrl> &datamover_0_cmd,
hls::stream<axis_datamover_ctrl> &datamover_1_cmd,
volatile ap_uint<1> &idle,
ap_uint<32> hbm_size_bytes) {
#pragma HLS INTERFACE ap_ctrl_none port=return
#pragma HLS INTERFACE register both axis port=data_in
@@ -22,15 +23,25 @@ void load_from_hbm(STREAM_512 &data_in,
#pragma HLS INTERFACE register both axis port=hbm_in_1
#pragma HLS INTERFACE register both axis port=datamover_0_cmd
#pragma HLS INTERFACE register both axis port=datamover_1_cmd
#pragma HLS INTERFACE register ap_none port=idle
#pragma HLS INTERFACE mode=ap_none port=hbm_size_bytes
idle = 1;
for (ap_uint<16> i = 0; i < hbm_size_bytes * 4 / (RAW_MODULE_SIZE * sizeof(uint16_t)); i++)
m_axis_free_handles << i;
packet_512_t packet;
packet_512_t packet;
data_in >> packet;
data_out << packet;
{
#pragma HLS PROTOCOL fixed
data_in >> packet;
ap_wait();
data_out << packet;
ap_wait();
idle = 0;
ap_wait();
}
ap_uint<32> offset_hbm_0 = 12 * hbm_size_bytes / 32;
ap_uint<32> offset_hbm_1 = 14 * hbm_size_bytes / 32;
@@ -76,4 +87,5 @@ void load_from_hbm(STREAM_512 &data_in,
data_in >> packet;
data_out << packet;
idle = 1;
}
+7 -3
View File
@@ -13,9 +13,13 @@ void mask_missing(STREAM_512 &data_in,
#pragma HLS INTERFACE register both axis port=s_axis_completion
packet_512_t packet;
data_in >> packet;
data_out << packet;
{
#pragma HLS PROTOCOL fixed
data_in >> packet;
ap_wait();
data_out << packet;
ap_wait();
}
axis_completion cmpl;
s_axis_completion >> cmpl;
while (!cmpl.last) {
+12 -5
View File
@@ -28,10 +28,11 @@ ap_uint<512> pack_and_reduce(const packed_pedestal_g0_t &in) {
unpack(in, tmp_full);
for (int i = 0; i < 32; i++) {
ap_ufixed<16,14, AP_RND_CONV> tmp1 = tmp_full[i]; // returns limited precision!
for (int j = 0; j < 16; j++) {
ap_uint<16> tmp1 = tmp_full[i] + pedestal_g0_t(0.5); // returns only integer part
if (tmp_full[i] > 16383)
tmp1 = 16384;
for (int j = 0; j < 16; j++)
out[i*16+j] = tmp1[j];
}
}
return out;
}
@@ -124,11 +125,17 @@ void pedestal(STREAM_512 &data_in, STREAM_512 &data_out,
frame_count[i] = 0;
packet_512_t packet;
data_in >> packet;
{
#pragma HLS PROTOCOL fixed
data_in >> packet;
ap_wait();
data_out << packet;
ap_wait();
}
ap_uint<8> conversion_mode = ACT_REG_MODE(packet.data);
ap_uint<8> nmodules = ACT_REG_NMODULES(packet.data) + 1;
ap_uint<5> nstoragecells = ACT_REG_NSTORAGE_CELLS(packet.data);
data_out << packet;
ap_uint<1> pedestal_mode = ((conversion_mode & MODE_PEDESTAL_G0) != 0)
|| ((conversion_mode & MODE_PEDESTAL_G1) != 0)
+19 -5
View File
@@ -11,6 +11,7 @@ void save_to_hbm(STREAM_512 &data_in,
hls::stream<ap_axiu<256,1,1,1> > &hbm_out_1,
hls::stream<axis_datamover_ctrl> &datamover_0_cmd,
hls::stream<axis_datamover_ctrl> &datamover_1_cmd,
volatile ap_uint<1> &idle,
ap_uint<32> hbm_size_bytes) {
#pragma HLS INTERFACE ap_ctrl_none port=return
#pragma HLS INTERFACE register both axis port=data_in
@@ -23,6 +24,9 @@ void save_to_hbm(STREAM_512 &data_in,
#pragma HLS INTERFACE register both axis port=datamover_0_cmd
#pragma HLS INTERFACE register both axis port=datamover_1_cmd
#pragma HLS INTERFACE mode=ap_none port=hbm_size_bytes
#pragma HLS INTERFACE register ap_none port=idle
idle = 1;
axis_completion cmpl[MAX_MODULES_FPGA*2];
@@ -34,12 +38,21 @@ void save_to_hbm(STREAM_512 &data_in,
}
packet_512_t packet_in;
data_in >> packet_in;
data_out << packet_in;
{
#pragma HLS PROTOCOL fixed
data_in >> packet_in;
ap_wait();
data_out << packet_in;
ap_wait();
idle = 0;
ap_wait();
}
ap_uint<32> offset_hbm_0 = 12 * hbm_size_bytes / 32;
ap_uint<32> offset_hbm_1 = 14 * hbm_size_bytes / 32;
data_in >> packet_in;
axis_addr addr;
addr_in >> addr;
@@ -82,8 +95,6 @@ void save_to_hbm(STREAM_512 &data_in,
setup_datamover(datamover_1_cmd, (offset_hbm_1 + offset) * 32, 4096);
for (int i = 0; i < 128; i++) {
data_in >> packet_in;
ap_axiu<256,1,1,1> packet_out;
packet_out.keep = UINT32_MAX;
packet_out.strb = UINT32_MAX;
@@ -97,6 +108,8 @@ void save_to_hbm(STREAM_512 &data_in,
packet_out.data = packet_in.data(511, 256);
hbm_out_1 << packet_out;
data_in >> packet_in;
}
addr_in >> addr;
@@ -117,7 +130,6 @@ void save_to_hbm(STREAM_512 &data_in,
}
}
data_in >> packet_in;
data_out << packet_in;
m_axis_completion << axis_completion{.last = 1};
@@ -125,4 +137,6 @@ void save_to_hbm(STREAM_512 &data_in,
ap_uint<16> tmp = s_axis_free_handles.read();
while (tmp != UINT16_MAX)
tmp = s_axis_free_handles.read();
idle = 1;
}
+11 -1
View File
@@ -10,7 +10,8 @@ void sls_detector(AXI_STREAM &udp_payload_in,
uint64_t& counter,
uint32_t& counter_eth_error,
uint32_t& counter_len_error,
volatile ap_uint<1> &in_clear_counters) {
volatile ap_uint<1> &in_clear_counters,
volatile ap_uint<1> &idle) {
#pragma HLS INTERFACE ap_ctrl_none port=return
#pragma HLS INTERFACE axis register both port=udp_payload_in
@@ -21,6 +22,7 @@ void sls_detector(AXI_STREAM &udp_payload_in,
#pragma HLS INTERFACE ap_vld register port=counter_eth_error
#pragma HLS INTERFACE ap_vld register port=counter_len_error
#pragma HLS INTERFACE ap_none register port=in_clear_counters
#pragma HLS INTERFACE ap_none register port=idle
#pragma HLS pipeline II=1 style=flp
@@ -54,6 +56,9 @@ void sls_detector(AXI_STREAM &udp_payload_in,
#pragma HLS RESET variable=internal_counter_len_error
#pragma HLS RESET variable=state
if (state == INSPECT_HEADER && udp_metadata_in.empty())
return;
if (udp_payload_in.read_nb(packet_in)) {
switch (state) {
@@ -110,4 +115,9 @@ void sls_detector(AXI_STREAM &udp_payload_in,
counter = internal_counter;
counter_eth_error = internal_counter_eth_error;
counter_len_error = internal_counter_len_error;
if (state == INSPECT_HEADER)
idle = 1;
else
idle = 0;
}
+40 -19
View File
@@ -27,8 +27,13 @@ struct spot_finder_packet {
void spot_finder_in_stream(STREAM_768 &data_in,
hls::stream<spot_finder_packet> &data_out) {
packet_768_t packet_in;
data_in >> packet_in;
data_out << spot_finder_packet{.data = packet_in.data, .user = packet_in.user, .last = packet_in.last};
{
#pragma HLS PROTOCOL fixed
data_in >> packet_in;
ap_wait();
data_out << spot_finder_packet{.data = packet_in.data, .user = packet_in.user, .last = packet_in.last};
ap_wait();
}
data_in >> packet_in;
while (!packet_in.user) {
#pragma HLS PIPELINE II=1
@@ -96,9 +101,12 @@ void spot_finder_prepare(hls::stream<spot_finder_packet> &data_in,
hls::stream<ap_int<SUM2_BITWIDTH>> &sum2_out,
hls::stream<ap_int<VALID_BITWIDTH>> &valid_out) {
spot_finder_packet packet;
data_in >> packet;
data_out << packet;
{
#pragma HLS PROTOCOL fixed
data_in >> packet;
data_out << packet;
ap_wait();
}
ap_int<SUM_BITWIDTH> sum[32];
ap_int<SUM2_BITWIDTH> sum2[32];
ap_int<VALID_BITWIDTH> valid[32];
@@ -139,7 +147,7 @@ void spot_finder_prepare(hls::stream<spot_finder_packet> &data_in,
}
ap_uint<32> spot_finder_snr_threshold(ap_int<24> val[32],
ap_uint<16> snr_threshold_2,
ap_ufixed<20,16, AP_RND_CONV> snr_threshold_2,
ap_int<SUM_BITWIDTH> sum,
ap_int<SUM2_BITWIDTH> sum2,
ap_int<VALID_BITWIDTH> valid_count) {
@@ -148,7 +156,7 @@ ap_uint<32> spot_finder_snr_threshold(ap_int<24> val[32],
return UINT32_MAX;
ap_int<SUM2_BITWIDTH+12> variance = valid_count * sum2 - sum * sum; // This is variance * valid_count^2
ap_int<SUM2_BITWIDTH+12+16> threshold = ((variance * snr_threshold_2 + 8) / (4*4));
ap_fixed<SUM2_BITWIDTH+12+16+1, SUM2_BITWIDTH+12+16> threshold = variance * snr_threshold_2;
// snr_threshold is in units of 0.25
ap_uint<32> ret = 0;
@@ -172,8 +180,7 @@ ap_uint<32> spot_finder_snr_threshold(ap_int<24> val[32],
return ret;
}
ap_uint<32> spot_finder_count_threshold(ap_int<24> val[32],
ap_int<16> &count_threshold) {
ap_uint<32> spot_finder_count_threshold(ap_int<24> val[32], ap_int<32> &count_threshold) {
#pragma HLS PIPELINE II=1
if (count_threshold <= 0)
return UINT32_MAX;
@@ -193,12 +200,17 @@ void spot_finder_apply_threshold(hls::stream<spot_finder_packet> &data_in,
hls::stream<ap_int<SUM2_BITWIDTH>> &sum2_in,
hls::stream<ap_int<VALID_BITWIDTH>> &valid_in,
hls::stream<ap_axiu<32,1,1,1>> &strong_pixel_out,
volatile ap_int<16> &in_count_threshold,
volatile ap_uint<8> &in_snr_threshold) {
volatile ap_int<32> &in_count_threshold,
volatile ap_uint<32> &in_snr_threshold) {
spot_finder_packet packet_in;
{
#pragma HLS PROTOCOL fixed
data_in >> packet_in;
ap_wait();
data_out << packet_768_t{.data = packet_in.data, .user = packet_in.user, .last = packet_in.last};
ap_wait();
}
data_in >> packet_in;
data_out << packet_768_t{.data = packet_in.data, .user = packet_in.user, .last = packet_in.last};
ap_int<SUM_BITWIDTH> sum[32];
ap_int<SUM2_BITWIDTH> sum2[32];
@@ -206,9 +218,18 @@ void spot_finder_apply_threshold(hls::stream<spot_finder_packet> &data_in,
data_in >> packet_in;
while (!packet_in.user) {
ap_int<16> count_threshold = in_count_threshold;
ap_uint<8> snr_threshold = in_snr_threshold;
ap_uint<16> snr_threshold_2 = snr_threshold * snr_threshold;
ap_int<32> count_threshold = in_count_threshold;
ap_uint<32> snr_threshold_u32 = in_snr_threshold;
float_uint32 thr;
thr.u = snr_threshold_u32;
ap_ufixed<10,8, AP_RND_CONV> snr_threshold = thr.f;
if (thr.f > 255)
snr_threshold = 255;
else if (thr.f <= 0)
snr_threshold = 0;
else
snr_threshold = thr.f;
ap_ufixed<20,16, AP_RND_CONV> snr_threshold_2 = snr_threshold * snr_threshold;
ap_uint<32> strong_pixel_count = 0;
for (int i = 0; i < RAW_MODULE_SIZE * sizeof(uint16_t) / 64; i++) {
#pragma HLS PIPELINE II=1
@@ -236,7 +257,7 @@ void spot_finder_apply_threshold(hls::stream<spot_finder_packet> &data_in,
// Save module statistics
strong_pixel_out << ap_axiu<32,1,1,1>{.data = count_threshold, .user = 0};
strong_pixel_out << ap_axiu<32,1,1,1>{.data = snr_threshold, .user = 0};
strong_pixel_out << ap_axiu<32,1,1,1>{.data = snr_threshold_u32, .user = 0};
strong_pixel_out << ap_axiu<32,1,1,1>{.data = strong_pixel_count, .user = 0};
for (int i = 0; i < 13; i++)
@@ -250,8 +271,8 @@ void spot_finder_apply_threshold(hls::stream<spot_finder_packet> &data_in,
void spot_finder(STREAM_768 &data_in,
STREAM_768 &data_out,
hls::stream<ap_axiu<32,1,1,1>> &strong_pixel_out,
volatile ap_int<16> &in_count_threshold,
volatile ap_uint<8> &in_snr_threshold) {
volatile ap_int<32> &in_count_threshold,
volatile ap_uint<32> &in_snr_threshold) {
#pragma HLS INTERFACE axis port=data_in
#pragma HLS INTERFACE axis port=data_out
#pragma HLS INTERFACE axis port=strong_pixel_out
+5 -4
View File
@@ -11,8 +11,10 @@ int main() {
STREAM_768 output;
hls::stream<ap_axiu<32, 1, 1, 1>> strong_pixel;
ap_int<16> in_photon_count_threshold = 8;
ap_uint<8> in_strong_pixel_threshold = 16;
ap_int<32> in_photon_count_threshold = 8;
float_uint32 in_strong_pixel_threshold;
in_strong_pixel_threshold.f = 4.0f;
ap_uint<32> local_strong_pixel_threshold = in_strong_pixel_threshold.u;
std::vector<int32_t> input_frame(nframes * RAW_MODULE_SIZE);
for (int i = 0; i < RAW_MODULE_SIZE; i++) {
@@ -33,8 +35,7 @@ int main() {
input << packet_768_t{.user = 1};
spot_finder(input, output, strong_pixel, in_photon_count_threshold,
in_strong_pixel_threshold);
spot_finder(input, output, strong_pixel, in_photon_count_threshold,local_strong_pixel_threshold);
if (input.size() != 0)
ret = 1;
+19 -4
View File
@@ -70,19 +70,33 @@ ap_uint<512> reduce_24_to_16_unsigned(ap_int<24*32> input) {
return pack32(tmp16);
}
void stream_24bit_conv(STREAM_768 &data_in, STREAM_512 &data_out) {
void stream_24bit_conv(STREAM_768 &data_in,
STREAM_512 &data_out,
volatile ap_uint<1> &idle) {
#pragma HLS INTERFACE axis register both port=data_in
#pragma HLS INTERFACE axis register both port=data_out
#pragma HLS INTERFACE ap_none register port=idle
idle = 1;
packet_768_t packet_in;
packet_512_t packet_out;
data_in >> packet_in;
{
#pragma HLS PROTOCOL fixed
data_in >> packet_in;
ap_wait();
data_out << packet_512_t{.data = packet_in.data, .user = 0, .last = 1};
ap_wait();
idle = 0;
ap_wait();
}
ap_uint<32> data_collection_mode = ACT_REG_MODE(packet_in.data);
ap_uint<1> write_32bit = ((data_collection_mode & MODE_32BIT) ? 1 : 0);
ap_uint<1> write_unsigned = ((data_collection_mode & MODE_UNSIGNED) ? 1 : 0);
data_out << packet_512_t{.data = packet_in.data, .user = 0, .last = 0};
data_in >> packet_in;
@@ -122,4 +136,5 @@ void stream_24bit_conv(STREAM_768 &data_in, STREAM_512 &data_out) {
}
}
data_out << packet_512_t{.data = packet_in.data, .user = 1, .last = 0};
idle = 1;
}
+3 -3
View File
@@ -28,15 +28,15 @@ void stream_merge(AXI_STREAM &input_100g,
bool rcv_eth_4x10g = input_4x10g.read_nb(packet_in_eth_4x10g);
if (data_source_local == STREAM_MERGE_SRC_100G) {
packet_in_eth_100g.id = AXI_STREAM_ID_ENABLE_ARP_ICMP;
packet_in_eth_100g.id = AXI_STREAM_ID_FULL_NETWORK_STACK;
if (rcv_eth_100g)
data_out.write(packet_in_eth_100g);
} else if (data_source_local == STREAM_MERGE_SRC_4x10G) {
packet_in_eth_4x10g.id = AXI_STREAM_ID_DISABLE_ARP_ICMP;
packet_in_eth_4x10g.id = AXI_STREAM_ID_SIMPLIFIED_NETWORK_STACK;
if (rcv_eth_4x10g)
data_out.write(packet_in_eth_4x10g);
} else if (data_source_local == STREAM_MERGE_SRC_FRAME_GEN) {
packet_in_frame_gen.id = AXI_STREAM_ID_DISABLE_ARP_ICMP;
packet_in_frame_gen.id = AXI_STREAM_ID_FULL_NETWORK_STACK;
if (rcv_frame_gen)
data_out.write(packet_in_frame_gen);
}
+8 -3
View File
@@ -13,13 +13,18 @@ void timer_host(STREAM_512 &data_in, STREAM_512 &data_out,
#pragma HLS INTERFACE ap_ctrl_none port=return
packet_512_t packet_in;
data_in >> packet_in;
{
#pragma HLS PROTOCOL fixed
data_in >> packet_in;
ap_wait();
data_out << packet_in;
ap_wait();
}
beats = 0;
uint64_t stalls_internal = 0;
stalls = 0;
uint64_t beats_internal = 0;
beats = 0;
data_out << packet_in;
data_in >> packet_in;
while (!packet_in.user) {
+7 -1
View File
@@ -7,7 +7,8 @@ void udp(AXI_STREAM &eth_in,
AXI_STREAM &udp_payload_out,
hls::stream<ap_uint<UDP_METADATA_STREAM_WIDTH> > &udp_metadata_out,
uint64_t& counter,
volatile ap_uint<1> &in_clear_counters) {
volatile ap_uint<1> &in_clear_counters,
volatile ap_uint<1> &idle) {
#pragma HLS INTERFACE ap_ctrl_none port=return
@@ -16,6 +17,7 @@ void udp(AXI_STREAM &eth_in,
#pragma HLS INTERFACE axis register both port=udp_metadata_out
#pragma HLS INTERFACE ap_vld register port=counter
#pragma HLS INTERFACE ap_none register port=in_clear_counters
#pragma HLS INTERFACE ap_none register port=idle
#pragma HLS pipeline II=1 style=flp
@@ -89,5 +91,9 @@ void udp(AXI_STREAM &eth_in,
}
counter = internal_counter;
if (state == INSPECT_HEADER)
idle = 1;
else
idle = 0;
}
+1 -2
View File
@@ -1,5 +1,4 @@
ADD_LIBRARY(JungfraujochDevice STATIC
JungfraujochDevice.cpp JungfraujochDevice.h)
ADD_LIBRARY(JungfraujochDevice STATIC JungfraujochDevice.cpp JungfraujochDevice.h ../include/jfjoch_fpga.h)
TARGET_LINK_LIBRARIES(JungfraujochDevice CommonFunctions)
-51
View File
@@ -1,51 +0,0 @@
// Copyright (2019-2023) Paul Scherrer Institute
#ifndef JUNGFRAUJOCH_DEVICEOUTPUT_H
#define JUNGFRAUJOCH_DEVICEOUTPUT_H
#include <cstdint>
#include "../../common/Definitions.h"
#pragma pack(push)
#pragma pack(1)
struct IntegrationResult {
uint32_t count;
float sum;
};
struct SpotFindingResult {
char strong_pixel[RAW_MODULE_SIZE / 8];
int32_t count_threshold;
int32_t snr_threshold;
int32_t strong_pixel_count;
int32_t reserved[13];
};
struct ModuleStatistics {
uint64_t frame_number;
uint64_t timestamp;
uint64_t bunchid;
uint64_t reserved_1;
uint64_t reserved_2;
uint32_t exptime;
uint32_t debug;
uint32_t pedestal;
uint32_t packet_count;
uint32_t module_number;
uint32_t reserved_3;
uint64_t packet_mask[4]; // This is reserved for 256 packets/module
};
struct DeviceOutput {
int16_t pixels[RAW_MODULE_SIZE * 2]; // accommodate 32-bit output
SpotFindingResult spot_finding_result;
IntegrationResult integration_result[FPGA_INTEGRATION_BIN_COUNT];
uint32_t adu_histogram[ADU_HISTO_BIN_COUNT];
ModuleStatistics module_statistics;
};
#pragma pack(pop)
#endif //JUNGFRAUJOCH_DEVICEOUTPUT_H
+10 -22
View File
@@ -3,7 +3,8 @@
#include <unistd.h>
#include <fcntl.h>
#include <sys/mman.h>
#include "../../common/Definitions.h"
#include "../include/jfjoch_fpga.h"
#include "JungfraujochDevice.h"
#include "../../common/JFJochException.h"
@@ -22,6 +23,11 @@ JungfraujochDevice::JungfraujochDevice(const std::string &device_name, bool writ
auto action_type = GetDataCollectionStatus().action_type;
if (action_type != ACTION_TYPE)
throw JFJochException(JFJochExceptionCategory::PCIeError, "Wrong device type");
auto action_release = GetDataCollectionStatus().release_level;
if (action_release != RELEASE_LEVEL)
throw JFJochException(JFJochExceptionCategory::PCIeError, "Mismatch of FPGA release between driver and library");
}
JungfraujochDevice::~JungfraujochDevice() {
@@ -88,6 +94,8 @@ uint32_t JungfraujochDevice::GetNumaNode() const {
}
void JungfraujochDevice::SetConfig(const DataCollectionConfig &config) {
if (config.nframes > MAX_FRAMES)
throw PCIeDeviceException("Cannot handle this many frames");
if (ioctl(fd, IOCTL_JFJOCH_SET_CONFIG, &config) != 0)
throw PCIeDeviceException("Failed writing config");
}
@@ -167,31 +175,11 @@ uint32_t JungfraujochDevice::ReadRegister(uint32_t addr) const {
return config.val;
}
void JungfraujochDevice::LoadCalibration(uint32_t modules, uint32_t storage_cells) {
DataCollectionConfig config{
.nmodules = modules,
.nstorage_cells = storage_cells
};
void JungfraujochDevice::LoadCalibration(const LoadCalibrationConfig &config) {
if (ioctl(fd, IOCTL_JFJOCH_LOAD_CALIB, &config) != 0)
throw PCIeDeviceException("Failed uploading calibration");
}
void JungfraujochDevice::LoadInternalGeneratorFrame(uint32_t modules) {
DataCollectionConfig config{
.nmodules = modules
};
if (ioctl(fd, IOCTL_JFJOCH_LOAD_INT_GEN, &config) != 0)
throw PCIeDeviceException("Failed uploading internal generator frame");
}
void JungfraujochDevice::LoadIntegrationMap(uint32_t modules) {
DataCollectionConfig config{
.nmodules = modules,
};
if (ioctl(fd, IOCTL_JFJOCH_LOAD_INT_MAP, &config) != 0)
throw PCIeDeviceException("Failed uploading integration map");
}
DeviceOutput *JungfraujochDevice::MapKernelBuffer(uint32_t id) {
auto tmp = (DeviceOutput *) mmap(nullptr, FPGA_BUFFER_LOCATION_SIZE,
PROT_READ | PROT_WRITE, MAP_SHARED,
+2 -11
View File
@@ -4,8 +4,7 @@
#define JUNGFRAUJOCH_JUNGFRAUJOCHDEVICE_H
#include <string>
#include "../pcie_driver/ActionConfig.h"
#include "DeviceOutput.h"
#include "../include/jfjoch_fpga.h"
struct JungfraujochDeviceCompletion {
uint16_t data_collection_id;
@@ -91,15 +90,7 @@ public:
// Load calibration parameters
// Function is synchronous - it will return when loading is done
void LoadCalibration(uint32_t modules, uint32_t storage_cells);
// Load frames for internal generator
// Must be placed in first <modules> kernel buffer locations
// Function is synchronous - it will return when loading is done
void LoadInternalGeneratorFrame(uint32_t modules);
// Load map of radial integration
// Must be placed in first <modules> kernel buffer locations
// Function is synchronous - it will return when loading is done
void LoadIntegrationMap(uint32_t modules);
void LoadCalibration(const LoadCalibrationConfig &config);
void SetSpotFinderParameters(const SpotFinderParameters &params);
SpotFinderParameters GetSpotFinderParameters();
+25 -6
View File
@@ -27,20 +27,39 @@ The first step for using the card is configuring network. To use network, one ne
The card will receive MAC address automatically based on Xilinx assigned number, but IPv4 address has to be configured with `JungfraujochDevice::SetIPv4Address()` function. The card is equipped with a simple network stack - if both MAC and IPv4 addresses are set and 100G interface is used, the card will periodically send ARP gratuitous messages, it will also reply to ARP requests and to ICMP pings. Given 4x10G interface is designed for direct Jungfraujoch-detector configuration, without a switch, diagnostics functionality is not offered here at the moment.
### Mapping kernel buffers
Next, kernel buffers need to be mapped to the user space. These buffers are allocated with memory physically continuous, simplyfing operation of the card and the driver. Count of these buffers can be checked with `JungfraujochDevice::GetBufferCount()` function. Buffers can be mapped with `JungfraujochDevice::MapKernelBuffer()` function and deallocated with `JungfraujochDevice::UnmapKernelBuffer()` functions. Structure of the kernel buffer is `DeviceOutput` and described in [include/jfjoch_fpga.h](../include/jfjoch_fpga.h) header file.
### Uploading calibration
Will be contributed later, as there is planned modification to the interface
Uploading calibration goes with two steps:
1. Copy the calibration data into one of kernel buffers mapped with `JungfraujochDevice::MapKernelBuffer()`. It requires to cast `DeviceOutput::pixels` element into a particular type (`float` or `uint16_t`).
2. Execute `JungfraujochDevice::LoadCalibration()` function for the card to upload the data. This function is synchronous and will return when the calibration is uploaded.
The following can be uploaded:
| destination | Bit-width | Data type (per pixel) | Description | Allowed value |
|-------------------------------------------|-----------|-----------------------|---------------------------------------|-----------------------------------------|
| LOAD_CALIBRATION_DEST_GAIN_G0 | 32 | float | 1/(gain parameter) | 0 - 0.125 (0 = mask pixel) |
| LOAD_CALIBRATION_DEST_GAIN_G1 | 32 | float | 1/(gain parameter) | -16.0 - 0.0 (0 = mask pixel) |
| LOAD_CALIBRATION_DEST_GAIN_G2 | 32 | float | 1/(gain parameter) | -64.0 - 0.0 (0 = mask pixel) |
| LOAD_CALIBRATION_DEST_PEDESTAL_G0 | 16 | uint16_t | pedestal, no fractional part | 0 - 16384 (16384 = mask pixel) |
| LOAD_CALIBRATION_DEST_PEDESTAL_G1 | 16 | uint16_t | pedestal, no fractional part | 0 - 16384 (16384 = mask pixel) |
| LOAD_CALIBRATION_DEST_PEDESTAL_G2 | 16 | uint16_t | pedestal, no fractional part | 0 - 16384 (16384 = mask pixel) |
| LOAD_CALIBRATION_DEST_INTEGRATION_MAP | 16 | uint16_t | integration bin | 0 - 1023 (higher values = ignore pixel) |
| LOAD_CALIBRATION_DEST_INTEGRATION_WEIGHTS | 32 | float | weight for the pixel | 0.0 - 2.0 |
| LOAD_CALIBRATION_DEST_FRAME_GEN | 16 | uint16_t | raw pixel values for generated frames | 0 - 65534 |
### Preparing data collection
Before any operation one needs to check if card is idle (not running data collection) with `JungfraujochDevice::IsIdle()` function. Most configuration parameters cannot be changed, when card is in not-idle state.
The card can be then configured with `JungfraujochDevice::SetConfig()` function. Details of the configuration data structure are given in [ActionConfig.h](../pcie_driver/ActionConfig.h) header file.
Next, kernel buffers need to be mapped to the user space. These buffers are allocated with memory physically continuous, simplyfing operation of the card and the driver. Count of these buffers can be checked with `JungfraujochDevice::GetBufferCount()` function. Buffers can be mapped with `JungfraujochDevice::MapKernelBuffer()` function and deallocated with `JungfraujochDevice::UnmapKernelBuffer()` functions. Structure of the kernel buffer is described in [DeviceOutput.h](DeviceOutput.h) header file.
The card can be then configured with `JungfraujochDevice::SetConfig()` function. Details of the configuration data structure are given in [include/jfjoch_fpga.h](../include/jfjoch_fpga.h) header file.
### Data collection
Then one can start the card with `JungfraujochDevice::Start()` function. Final step is to wait for first completion (with value `HANDLE_START` defined in [Definitions.h](../../common/Definitions.h) as buffer number) using `JungfraujochDevice::ReadWorkCompletion()`.
Then one can start the card with `JungfraujochDevice::Start()` function. Final step is to wait for first completion (with value `HANDLE_START` defined in [include/jfjoch_fpga.h](../include/jfjoch_fpga.h) as buffer number) using `JungfraujochDevice::ReadWorkCompletion()`.
Standard operation of the card requires exchange of buffer ownership between the host application and FPGA card. At the beginning all buffers are owned by host application and should be "given" to the card with `JungfraujochDevice::SendWorkRequest()` function. Then card will wait for the detector to send data. After full module is collected, data are written via Direct Memory Access to host memory and kernel driver is informed with an interrupt that data are ready. Host application can "learn" what was collected by the card by running `JungfraujochDevice::ReadWorkCompletion()` function. Buffer returned by the function is owned by the host application and is safe to process. After processing the buffer has to be given back to card via `JungfraujochDevice::SendWorkRequest()`. If the card doesn't receive enough work requests (open buffers) it won't be able to receive data, resulting in lost packets.
@@ -66,7 +85,7 @@ To load the data, one needs to place content of each module (in 16-bit) into res
One also needs to switch data source by executing `JungfraujochDevice::SetDataSource()` with respective value.
The next step is to do all the preparations to start data collection, up to `JungfraujochDevice::Start()` and completion handshake. Then one can run `JungfraujochDevice::RunFrameGenerator()` function, with parameters described in the [ActionConfig.h](../pcie_driver/ActionConfig.h) header file. The function is asynchronous, and will start generation, but doesn't wait for the end. Though one can assume that frame generator is done, when data collection is finished.
The next step is to do all the preparations to start data collection, up to `JungfraujochDevice::Start()` and completion handshake. Then one can run `JungfraujochDevice::RunFrameGenerator()` function, with parameters described in the [include/jfjoch_fpga.h](../include/jfjoch_fpga.h) header file. The function is asynchronous, and will start generation, but doesn't wait for the end. Though one can assume that frame generator is done, when data collection is finished.
### Spot finding parameters
Spot finding parameters can be updated with function `JungfraujochDevice::SetSpotFinderParameters()`.

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