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:
1 parent
b1d9bb3988
commit
25542a9af3
9 files changed
+77
-8
No files matched your search
@@ -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);
|
||||
}
|
||||
|
||||
|
||||
@@ -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++) {
|
||||
|
||||
@@ -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();
|
||||
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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));
|
||||
}
|
||||
Reference in new issue
Block a user