acquisition_device: refuse internal generator images the card memory cannot hold

With modules x images at or above what the card's HBM holds for the
internal frame generator (64 module frames in the HLS simulation, 1024 on
the card), frame_generator refuses the run and sends nothing, and the
collection hung in Measuring with no error. The host now checks this:
PrepareAction refuses such a run at the start (a 32-bit EIGER frame
counts twice, as in frame_generator.cpp), and SetInternalGeneratorFrame
refuses an image that would land there, each with an error that says
how many module frames fit. The capacity comes from hbm_size_bytes of
the card's status (the mock keeps its 64).

The check keeps the last module frame free as well: load_calibration.cpp
accepts module_id == 2 * hbm_size_bytes / module size (">" where ">="
was meant), one past the memory. The firmware is frozen, so the host
never sends that index instead.

The HLS simulation keeps frame_generator's return code: a refused
configuration cancels the data collection rather than waiting for frames,
and HLSSimulatedDevice::FPGA_EndAction throws with the code.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01HVeDQsU5a8AJUdJPgWevAK
This commit is contained in:
leonarski_fandClaude Opus 5.5 committed 2026-11-08 11:33:37 +01:00
1 parent b1d9bb3988
commit 25542a9af3
9 files changed
+77 -8

No files matched your search

+23
View File
@@ -14,11 +14,34 @@ AcquisitionDevice::AcquisitionDevice(uint16_t in_data_stream) {
data_stream = in_data_stream;
}
uint64_t AcquisitionDevice::GeneratorModuleFrames(uint32_t hbm_size_bytes) {
return 2 * static_cast<uint64_t>(hbm_size_bytes) / (RAW_MODULE_SIZE * sizeof(uint16_t));
}
// frame_generator.cpp refuses a run that fills its memory, and load_calibration.cpp lets one module frame past it
// through, so the host keeps the last one free.
void AcquisitionDevice::CheckInternalGeneratorFrame(size_t module_frame) const {
if (module_frame + 1 >= internal_generator_module_frames)
throw JFJochException(JFJochExceptionCategory::InputParameterAboveMax,
"Internal frame generator: the card memory holds "
+ std::to_string(internal_generator_module_frames - 1)
+ " module frames (modules x images), this needs "
+ std::to_string(module_frame + 1));
}
void AcquisitionDevice::PrepareAction(const DiffractionExperiment &experiment) {
if (experiment.GetModulesNum(data_stream) > max_modules)
throw(JFJochException(JFJochExceptionCategory::InputParameterAboveMax,
"Number of modules exceeds max possible for FPGA"));
if (experiment.IsUsingInternalPacketGen()) {
int64_t module_frames = experiment.GetModulesNum(data_stream) * experiment.GetInternalPacketGeneratorImages();
// A 32-bit EIGER frame takes two
if ((experiment.GetDetectorType() == DetectorType::EIGER) && (experiment.GetBitDepthReadout() == 32))
module_frames *= 2;
CheckInternalGeneratorFrame(module_frames - 1);
}
counters.Reset(experiment, data_stream);
}
+6
View File
@@ -57,6 +57,10 @@ protected:
uint16_t data_stream;
uint32_t max_modules = 1;
// Module frames the card memory holds for the internal frame generator
uint64_t internal_generator_module_frames = 0;
// As frame_generator.cpp: the frames are in two HBM interfaces of hbm_size_bytes each
static uint64_t GeneratorModuleFrames(uint32_t hbm_size_bytes);
uint64_t mac_addr;
uint32_t ipv4_addr;
explicit AcquisitionDevice(uint16_t data_stream);
@@ -117,5 +121,7 @@ public:
virtual uint32_t GetExpectedDescriptorsPerModule() const = 0;
void RunInternalGenerator(const DiffractionExperiment& experiment);
// The module frame of the internal frame generator's images, throws if the card memory cannot hold it
void CheckInternalGeneratorFrame(size_t module_frame) const;
};
@@ -123,6 +123,7 @@ void FPGAAcquisitionDevice::InitializeIntegrationMap(const uint16_t *map, const
}
void FPGAAcquisitionDevice::SetInternalGeneratorFrame(const uint16_t *input, size_t module_number) {
CheckInternalGeneratorFrame(module_number);
memcpy(buffer_device[0]->pixels, input, RAW_MODULE_SIZE * sizeof(uint16_t));
buffer_device[0]->module_statistics.module_number = module_number;
buffer_device[0]->module_statistics.load_calibration_destination = LOAD_CALIBRATION_DEST_FRAME_GEN;
@@ -17,6 +17,7 @@ HLSSimulatedDevice::HLSSimulatedDevice(uint16_t data_stream, size_t in_frame_buf
}
device = std::make_unique<HLSDevice>(buffer_device);
internal_generator_module_frames = GeneratorModuleFrames(device->GetDataCollectionStatus().hbm_size_bytes);
}
void HLSSimulatedDevice::CreateFinalPacket(const DiffractionExperiment& experiment) {
@@ -60,6 +61,9 @@ void HLSSimulatedDevice::HW_RunInternalGenerator(const FrameGeneratorConfig &con
void HLSSimulatedDevice::FPGA_EndAction() {
device->FPGA_EndAction();
if (const int result = device->GetFrameGeneratorResult(); result != 0)
throw JFJochException(JFJochExceptionCategory::AcquisitionDeviceError,
"Internal frame generator refused its configuration, error code " + std::to_string(result));
}
@@ -26,6 +26,8 @@ MockAcquisitionDevice::MockAcquisitionDevice(uint16_t data_stream, size_t in_fra
ipv4_addr = 0x0132010A;
max_modules = MAX_MODULES_FPGA;
// As FrameGenerator below
internal_generator_module_frames = 64;
buffers.reserve(in_frame_buffer_size_modules);
for (size_t i = 0; i < in_frame_buffer_size_modules; i++) {
+1
View File
@@ -20,6 +20,7 @@ PCIExpressDevice::PCIExpressDevice(uint16_t data_stream, const std::string &devi
max_modules = status.max_modules;
if (max_modules == 0)
throw JFJochException(JFJochExceptionCategory::PCIeError, "Max modules cannot be zero");
internal_generator_module_frames = GeneratorModuleFrames(status.hbm_size_bytes);
uint32_t num_buf = GetNumKernelBuffers();
+16 -8
View File
@@ -216,17 +216,25 @@ void HLSDevice::FPGA_StartAction() {
}
void HLSDevice::FrameGeneratorFuture(FrameGeneratorConfig config) {
frame_generator(impl_->din_eth,
impl_->hbm.data(),
impl_->hbm.data(),
impl_->hbm_if_size,
mac_addr,
ipv4_addr,
impl_->cancel_data_collection,
config);
frame_generator_result = frame_generator(impl_->din_eth,
impl_->hbm.data(),
impl_->hbm.data(),
impl_->hbm_if_size,
mac_addr,
ipv4_addr,
impl_->cancel_data_collection,
config);
// A generator that refused its configuration sends no frame: the data collection ends instead of waiting for them
if (frame_generator_result != 0)
impl_->cancel_data_collection = 1;
}
int HLSDevice::GetFrameGeneratorResult() const {
return frame_generator_result;
}
void HLSDevice::HW_RunInternalGenerator(const FrameGeneratorConfig &config) {
frame_generator_result = 0;
frame_generator_future = std::async(std::launch::async, &HLSDevice::FrameGeneratorFuture, this, config);
}
+4
View File
@@ -3,6 +3,7 @@
#pragma once
#include <atomic>
#include <future>
#include <vector>
@@ -19,6 +20,7 @@ class HLSDevice {
std::thread action_thread;
std::future<void> frame_generator_future;
std::atomic<int> frame_generator_result{0};
std::vector<uint64_t> dma_address_table;
uint64_t eth_packets = 0;
uint64_t icmp_packets = 0;
@@ -52,6 +54,8 @@ public:
void CreateXfelBunchIDPacket(double bunchid, uint32_t event_code);
DataCollectionStatus GetDataCollectionStatus() const ;
// What frame_generator returned in the last run, 0 if it was not run or went fine
int GetFrameGeneratorResult() const;
void Cancel() ;
void HW_ReadActionRegister(DataCollectionConfig *job);
+20
View File
@@ -447,3 +447,23 @@ TEST_CASE("MockAcquisitionDevice_SameAsHLS_Receiver", "[MockAcquisitionDevice][H
CHECK(memcmp(mock_plots[i].data(), hls_plots[i].data(), hls_plots[i].size() * sizeof(float)) == 0);
}
}
TEST_CASE("MockAcquisitionDevice_InternalGeneratorMemory", "[MockAcquisitionDevice]") {
// 64 module frames in the card memory; the generator takes 63 at most
DiffractionExperiment x(DetJF(2));
x.UseInternalPacketGenerator(true).ImagesPerTrigger(1).NumTriggers(1);
MockAcquisitionDevice device(0, 64);
HLSSimulatedDevice hls_device(0, 64);
x.InternalPacketGeneratorImages(31);
REQUIRE_NOTHROW(device.PrepareAction(x));
REQUIRE_NOTHROW(hls_device.PrepareAction(x));
x.InternalPacketGeneratorImages(32);
REQUIRE_THROWS(device.PrepareAction(x));
REQUIRE_THROWS(hls_device.PrepareAction(x));
std::vector<uint16_t> frame(RAW_MODULE_SIZE);
REQUIRE_NOTHROW(hls_device.SetInternalGeneratorFrame(frame.data(), 62));
REQUIRE_THROWS(hls_device.SetInternalGeneratorFrame(frame.data(), 63));
}