// SPDX-FileCopyrightText: 2024 Filip Leonarski, Paul Scherrer Institute // SPDX-License-Identifier: GPL-3.0-only #include #include "AcquisitionCounters.h" #include "../common/JFJochException.h" AcquisitionCounters::AcquisitionCounters() : curr_frame_number(max_modules, 0), slowest_frame_number(0), fastest_frame_number(0), total_packets(0), expected_frames(0), acquisition_finished(false) {} void AcquisitionCounters::Reset(const DiffractionExperiment &experiment, uint16_t data_stream) { std::unique_lock ul(m); acquisition_finished = false; slowest_frame_number = 0; fastest_frame_number = 0; if ((experiment.GetDetectorMode() == DetectorMode::PedestalG0) || (experiment.GetDetectorMode() == DetectorMode::PedestalG1) || (experiment.GetDetectorMode() == DetectorMode::PedestalG2)) expected_frames = experiment.GetFrameNum(); else expected_frames = experiment.GetFrameNum() / experiment.GetFPGASummation(); nmodules = experiment.GetModulesNum(data_stream); if (nmodules > max_modules) throw JFJochException(JFJochExceptionCategory::InputParameterInvalid, "Acquisition counter cannot support that many modules"); for (int i = 0; i < max_modules; i++) curr_frame_number[i] = 0; handle_for_frame = std::vector(expected_frames * nmodules, HandleNotFound); handle_for_pedestal = std::vector(nmodules * 16, HandleNotFound); // 16 = storage cells packets_collected = std::vector(expected_frames * nmodules); saved_completions = std::vector(expected_frames * nmodules); packets_per_module = std::vector(nmodules); total_packets = 0; expected_packets_per_module = 512 * experiment.GetFPGASummation(); if (experiment.GetByteDepthReadout() == 4) bytes_per_packet = 4096LU; else if (experiment.GetByteDepthReadout() == 1) bytes_per_packet = 1024LU; // Need to seriously refactor, to have expected_packets_per_module specific for detector else bytes_per_packet = 2048LU; } void AcquisitionCounters::UpdateCounters(const Completion *c) { std::unique_lock ul(m); 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) + " and handle " + std::to_string(c->handle)); if (c->frame_number >= expected_frames) throw JFJochException(JFJochExceptionCategory::InputParameterInvalid, "UpdateCounters frame number is out of bounds"); else { if (curr_frame_number.at(c->module_number) < c->frame_number) curr_frame_number.at(c->module_number) = c->frame_number; if (c->frame_number > slowest_frame_number) { slowest_frame_number = curr_frame_number[0]; for (int i = 1; i < nmodules; i++) if (curr_frame_number[i] < slowest_frame_number) slowest_frame_number = curr_frame_number[i]; } if (c->frame_number > fastest_frame_number) { fastest_frame_number = c->frame_number; } packets_collected.at(c->frame_number * nmodules + c->module_number) = c->packet_count; handle_for_frame.at(c->frame_number * nmodules + c->module_number) = c->handle; saved_completions.at(c->frame_number * nmodules + c->module_number) = *c; total_packets += c->packet_count; packets_per_module[c->module_number] += c->packet_count; } data_updated.notify_all(); } void AcquisitionCounters::SetAcquisitionFinished() { std::unique_lock ul(m); acquisition_finished = true; data_updated.notify_all(); } uint64_t AcquisitionCounters::GetBufferHandle(size_t frame, uint16_t module_number) const { if (frame >= expected_frames) throw JFJochException(JFJochExceptionCategory::ArrayOutOfBounds, "GetBufferHandle Wrong frame number: " + std::to_string(frame)); if (module_number >= nmodules) throw JFJochException(JFJochExceptionCategory::ArrayOutOfBounds, "GetBufferHandle Wrong module number: " + std::to_string(module_number) + " for frame " + std::to_string(frame)); return handle_for_frame.at(frame * nmodules + module_number); } uint64_t AcquisitionCounters::GetBufferHandleAndClear(size_t frame, uint16_t module_number) { std::unique_lock ul(m); if (frame >= expected_frames) throw JFJochException(JFJochExceptionCategory::ArrayOutOfBounds, "GetBufferHandleAndClear Wrong frame number: " + std::to_string(frame)); if (module_number >= nmodules) throw JFJochException(JFJochExceptionCategory::ArrayOutOfBounds, "GetBufferHandleAndClear Wrong module number: " + std::to_string(module_number) + " for frame " + std::to_string(frame)); uint64_t ret_val = handle_for_frame.at(frame * nmodules + module_number); handle_for_frame.at(frame * nmodules + module_number) = HandleNotFound; return ret_val; } uint64_t AcquisitionCounters::GetPedestalBufferHandle(size_t storage_cell, uint16_t module_number) const { std::unique_lock ul(m); if (storage_cell >= 16) throw JFJochException(JFJochExceptionCategory::ArrayOutOfBounds, "GetBufferHandleAndClear Wrong frame number: " + std::to_string(storage_cell)); if (module_number >= nmodules) throw JFJochException(JFJochExceptionCategory::ArrayOutOfBounds, "GetBufferHandleAndClear Wrong module number: " + std::to_string(module_number) + " for SC " + std::to_string(storage_cell)); return handle_for_pedestal.at(storage_cell * nmodules + module_number); } uint64_t AcquisitionCounters::GetCurrFrameNumber(uint16_t module_number) const { if (module_number >= max_modules) throw JFJochException(JFJochExceptionCategory::ArrayOutOfBounds, "GetCurrFrameNumber Wrong module number: " + std::to_string(module_number)); return curr_frame_number[module_number]; } uint64_t AcquisitionCounters::GetSlowestFrameNumber() const { return slowest_frame_number; } uint64_t AcquisitionCounters::GetFastestFrameNumber() const { return fastest_frame_number; } void AcquisitionCounters::WaitForFrame(size_t curr_frame, uint16_t module_number) const { uint64_t slowest_head_tmp = (module_number == UINT16_MAX) ? GetSlowestFrameNumber() : GetCurrFrameNumber(module_number); if (curr_frame == 0) curr_frame = 1; // Cannot wait for frame 0, as this is initial value of slowest frame number, so waiting for frame 1 in this case while (!acquisition_finished && (slowest_head_tmp < curr_frame)) { std::this_thread::sleep_for(std::chrono::microseconds(100)); slowest_head_tmp = (module_number == UINT16_MAX) ? GetSlowestFrameNumber() : GetCurrFrameNumber(module_number); } } int64_t AcquisitionCounters::CalculateDelay(size_t curr_frame, uint16_t module_number) const { uint64_t slowest_head_tmp; if (module_number == UINT16_MAX) slowest_head_tmp = GetSlowestFrameNumber(); else slowest_head_tmp = GetCurrFrameNumber(module_number); if (slowest_head_tmp < curr_frame) return 0; return slowest_head_tmp - curr_frame; } bool AcquisitionCounters::IsAcquisitionFinished() const { return acquisition_finished; } bool AcquisitionCounters::IsFullModuleCollected(size_t frame, uint16_t module_number) const { if (frame >= expected_frames) throw JFJochException(JFJochExceptionCategory::ArrayOutOfBounds, "IsFullModuleCollected Wrong frame number: " + std::to_string(frame)); if (module_number >= nmodules) throw JFJochException(JFJochExceptionCategory::ArrayOutOfBounds, "IsFullModuleCollected Wrong module number: " + std::to_string(module_number) + " for frame " + std::to_string(frame)); return packets_collected[frame * nmodules + module_number] == expected_packets_per_module; } bool AcquisitionCounters::IsAnyPacketCollected(size_t frame, uint16_t module_number) const { if (frame >= expected_frames) throw JFJochException(JFJochExceptionCategory::ArrayOutOfBounds, "IsFullModuleCollected Wrong frame number: " + std::to_string(frame)); if (module_number >= nmodules) throw JFJochException(JFJochExceptionCategory::ArrayOutOfBounds, "IsFullModuleCollected Wrong module number: " + std::to_string(module_number) + " for frame " + std::to_string(frame)); return packets_collected[frame * nmodules + module_number] > 0; } uint64_t AcquisitionCounters::GetTotalPackets() const { return total_packets; } uint64_t AcquisitionCounters::GetTotalPackets(uint16_t module_number) const { std::unique_lock ul(m); if (module_number >= nmodules) throw JFJochException(JFJochExceptionCategory::ArrayOutOfBounds, "GetTotalPackets Wrong module number: " + std::to_string(module_number)); return packets_per_module[module_number]; } uint64_t AcquisitionCounters::GetExpectedPackets() const { return GetExpectedPacketsPerModule() * nmodules; } uint64_t AcquisitionCounters::GetExpectedPacketsPerModule() const { return expected_frames * expected_packets_per_module; } uint64_t AcquisitionCounters::GetModuleNumber() const { return nmodules; } uint64_t AcquisitionCounters::GetBytesReceived() const { return GetTotalPackets() * bytes_per_packet; }