diff --git a/receiver/AcquisitionDevice.cpp b/receiver/AcquisitionDevice.cpp index 07ff8766..f4655da3 100644 --- a/receiver/AcquisitionDevice.cpp +++ b/receiver/AcquisitionDevice.cpp @@ -33,7 +33,7 @@ void *mmap_acquisition_buffer(size_t size, int16_t numa_node) { } AcquisitionDevice::AcquisitionDevice(uint16_t in_data_stream) : -buffer_err(RAW_MODULE_SIZE) { +buffer_err(FPGA_BUFFER_LOCATION_SIZE) { logger = nullptr; data_stream = in_data_stream; } @@ -161,6 +161,10 @@ const int16_t *AcquisitionDevice::GetFrameBuffer(size_t frame_number, uint16_t m return GetErrorFrameBuffer(); } +const IntegrationResult *AcquisitionDevice::GetIntegrationResult(size_t frame_number, uint16_t module_number) const { + return reinterpret_cast(GetFrameBuffer(frame_number, module_number) + RAW_MODULE_SIZE); +} + const int16_t *AcquisitionDevice::GetErrorFrameBuffer() const { return buffer_err.data(); } @@ -174,6 +178,9 @@ int16_t *AcquisitionDevice::GetDeviceBuffer(size_t handle) { void AcquisitionDevice::InitializeCalibration(const DiffractionExperiment &experiment, const JFCalibration &calib) {} +void AcquisitionDevice::InitializeIntegrationMap(const DiffractionExperiment &experiment, + const std::vector &v) {} + void AcquisitionDevice::MapBuffersStandard(size_t c2h_buffer_count, size_t h2c_buffer_count, int16_t numa_node) { try { for (int i = 0; i < std::max(c2h_buffer_count, h2c_buffer_count); i++) diff --git a/receiver/AcquisitionDevice.h b/receiver/AcquisitionDevice.h index 309167ea..44fc7c9f 100644 --- a/receiver/AcquisitionDevice.h +++ b/receiver/AcquisitionDevice.h @@ -20,6 +20,11 @@ #include "AcquisitionCounters.h" #include "Completion.h" +struct IntegrationResult { + int64_t sum; + int64_t count; +}; + class AcquisitionDevice { std::vector buffer_err; @@ -71,6 +76,7 @@ public: virtual JFJochProtoBuf::FPGAStatus GetStatus() const { return {}; }; const int16_t *GetFrameBuffer(size_t frame_number, uint16_t module_number) const; + const IntegrationResult *GetIntegrationResult(size_t frame_number, uint16_t module_number) const; void FrameBufferRelease(size_t frame_number, uint16_t module_number); const int16_t *GetErrorFrameBuffer() const; @@ -79,7 +85,7 @@ public: // Calibration virtual void InitializeCalibration(const DiffractionExperiment &experiment, const JFCalibration &calib); - + virtual void InitializeIntegrationMap(const DiffractionExperiment &experiment, const std::vector &v); const AcquisitionCounters& Counters() const; virtual std::string GetIPv4Address() const; diff --git a/receiver/FPGAAcquisitionDevice.cpp b/receiver/FPGAAcquisitionDevice.cpp index ee7a4352..7fa12c8b 100644 --- a/receiver/FPGAAcquisitionDevice.cpp +++ b/receiver/FPGAAcquisitionDevice.cpp @@ -60,6 +60,26 @@ void FPGAAcquisitionDevice::SendWorkRequestThread() { } } +void FPGAAcquisitionDevice::InitializeIntegrationMap(const DiffractionExperiment &experiment, + const std::vector &v) { + auto offset = experiment.GetFirstModuleOfDataStream(data_stream); + + if (v.size() != experiment.GetModulesNum() * RAW_MODULE_SIZE) + throw JFJochException(JFJochExceptionCategory::InputParameterInvalid, + "Mismatch regarding integration map array"); + + size_t modules = experiment.GetModulesNum(data_stream); + + if (modules > 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)); + + HW_LoadIntegrationMap(modules); +} + void FPGAAcquisitionDevice::InitializeCalibration(const DiffractionExperiment &experiment, const JFCalibration &calib) { auto offset = experiment.GetFirstModuleOfDataStream(data_stream); @@ -78,6 +98,11 @@ void FPGAAcquisitionDevice::InitializeCalibration(const DiffractionExperiment &e throw JFJochException(JFJochExceptionCategory::InputParameterInvalid, "Not enough host/FPGA buffers to load all calibration constants"); + if (modules * (3 + 3 * storage_cells) > LOAD_CALIBRATION_BRAM_SIZE) + throw JFJochException(JFJochExceptionCategory::InputParameterInvalid, + "FPGA is not compatible with that many calibration constants"); + + for (int m = 0; m < modules; m++) { calib.GainCalibration(m).ExportG0(buffer_device[m]); calib.GainCalibration(m).ExportG1(buffer_device[m + modules]); diff --git a/receiver/FPGAAcquisitionDevice.h b/receiver/FPGAAcquisitionDevice.h index 02dce660..c59af2b3 100644 --- a/receiver/FPGAAcquisitionDevice.h +++ b/receiver/FPGAAcquisitionDevice.h @@ -27,6 +27,7 @@ class FPGAAcquisitionDevice : public AcquisitionDevice { void SendWorkRequestThread(); virtual void HW_LoadCalibration(uint32_t modules, uint32_t storage_cells) = 0; + virtual void HW_LoadIntegrationMap(uint32_t modules) = 0; virtual bool HW_ReadMailbox(uint32_t values[16]) = 0; virtual bool HW_SendWorkRequest(uint32_t handle) = 0; void StartSendingWorkRequests() override; @@ -42,7 +43,7 @@ public: ActionConfig ReadActionRegister(); JFJochProtoBuf::FPGAStatus GetStatus() const override; void InitializeCalibration(const DiffractionExperiment &experiment, const JFCalibration &calib) override; - + void InitializeIntegrationMap(const DiffractionExperiment &experiment, const std::vector &v) override; void SetCustomInternalGeneratorFrame(const std::vector &v); std::vector GetInternalGeneratorFrame() const override; }; diff --git a/receiver/HLSSimulatedDevice.cpp b/receiver/HLSSimulatedDevice.cpp index 0601d5a9..25db6a98 100644 --- a/receiver/HLSSimulatedDevice.cpp +++ b/receiver/HLSSimulatedDevice.cpp @@ -456,6 +456,33 @@ void HLSSimulatedDevice::HW_LoadCalibration(uint32_t modules, uint32_t storage_c throw std::runtime_error("Datamover queue is not empty"); } +void HLSSimulatedDevice::HW_LoadIntegrationMap(uint32_t modules) { + if (logger) + logger->Info("Load calibration start"); + + auto in_mem_location32 = (uint32_t *) calibration_addr_bram; + + for (int i = 0; i < modules; i++) { + in_mem_location32[2 * i ] = ((uint64_t) buffer_device[i]) & UINT32_MAX; + in_mem_location32[2 * i + 1] = ((uint64_t) buffer_device[i]) >> 32; + } + + load_calibration(hbm.data(), + hbm.data(), + modules, + 0, + hbm_if_size, + LOAD_CALIBRATION_DEST_INTEGRATION, + datamover_in.GetCtrlStream(), + datamover_in.GetDataStream(), + calibration_addr_bram); + if (logger) + logger->Info("Load integration_map"); + + if (!datamover_in.GetDataStream().empty()) + throw std::runtime_error("Datamover queue is not empty"); +} + uint32_t HLSSimulatedDevice::GetCompletedDescriptors() const { return datamover_out.GetCompletedDescriptors(); } \ No newline at end of file diff --git a/receiver/HLSSimulatedDevice.h b/receiver/HLSSimulatedDevice.h index 71ced6ff..0d96ae58 100644 --- a/receiver/HLSSimulatedDevice.h +++ b/receiver/HLSSimulatedDevice.h @@ -52,6 +52,7 @@ class HLSSimulatedDevice : public FPGAAcquisitionDevice { bool HW_ReadMailbox(uint32_t values[16]) 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_GetStatus(ActionStatus *status) const override; void HLSMainThread() ; void RunFrameGenerator(const FrameGeneratorConfig& config); diff --git a/receiver/PCIExpressDevice.cpp b/receiver/PCIExpressDevice.cpp index df708470..60d9aabf 100644 --- a/receiver/PCIExpressDevice.cpp +++ b/receiver/PCIExpressDevice.cpp @@ -234,8 +234,15 @@ void PCIExpressDevice::HW_LoadCalibration(uint32_t in_modules, uint32_t in_stora .nstorage_cells = in_storage_cells }; if (ioctl(fd, IOCTL_JFJOCH_LOAD_CALIB, &config) != 0) - throw JFJochException(JFJochExceptionCategory::PCIeError, - "Failed writing config", errno); + throw JFJochException(JFJochExceptionCategory::PCIeError, "Failed uploading calibration", errno); +} + +void PCIExpressDevice::HW_LoadIntegrationMap(uint32_t in_modules) { + ActionConfig config{ + .nmodules = in_modules, + }; + if (ioctl(fd, IOCTL_JFJOCH_LOAD_INT_MAP, &config) != 0) + throw JFJochException(JFJochExceptionCategory::PCIeError, "Failed uploading integration map", errno); } uint32_t PCIExpressDevice::GetCompletedDescriptors() const { diff --git a/receiver/PCIExpressDevice.h b/receiver/PCIExpressDevice.h index f7f956da..46d93cac 100644 --- a/receiver/PCIExpressDevice.h +++ b/receiver/PCIExpressDevice.h @@ -15,6 +15,7 @@ class PCIExpressDevice : public FPGAAcquisitionDevice { void HW_WriteActionRegister(const ActionConfig *job) override; void HW_ReadActionRegister(ActionConfig *job) override; void HW_LoadCalibration(uint32_t modules, uint32_t storage_cells) override; + void HW_LoadIntegrationMap(uint32_t modules) override; void FPGA_EndAction() override; void Reset(); diff --git a/tests/FPGAIntegrationTest.cpp b/tests/FPGAIntegrationTest.cpp index efc793de..0d7f09fc 100644 --- a/tests/FPGAIntegrationTest.cpp +++ b/tests/FPGAIntegrationTest.cpp @@ -1030,3 +1030,63 @@ TEST_CASE("HLS_C_Simulation_internal_packet_generator_storage_cell_convert_G1", } } +TEST_CASE("HLS_C_Simulation_internal_packet_generator_integration", "[FPGA][Full]") { + const uint16_t nmodules = 4; + + DiffractionExperiment x((DetectorGeometry(nmodules))); + + x.Mode(DetectorMode::Raw); + x.UseInternalPacketGenerator(true).ImagesPerTrigger(1).PedestalG0Frames(0); + + HLSSimulatedDevice test(0, 64); + + std::vector frame(RAW_MODULE_SIZE); + frame[0] = INT16_MAX; + frame[1] = INT16_MIN; + + for (int i = 2; i < RAW_MODULE_SIZE; i++) + frame[i] = 32754; + + test.SetCustomInternalGeneratorFrame(frame); + + std::vector integration_map(nmodules * RAW_MODULE_SIZE, 54); + for (int i = 0; i < RAW_MODULE_SIZE/2; i++) { + integration_map[2 * i] = 0; + integration_map[2 * i + 1] = FPGA_INTEGRATION_BIN_COUNT - 1; + } + + integration_map[RAW_MODULE_SIZE - 1] = FPGA_INTEGRATION_BIN_COUNT; + test.InitializeIntegrationMap(x, integration_map); + + REQUIRE_NOTHROW(test.StartAction(x)); + REQUIRE_NOTHROW(test.WaitForActionComplete()); + + REQUIRE(test.OutputStream().size() == 1); + + JFJochProtoBuf::AcquisitionDeviceStatistics device_statistics; + REQUIRE_NOTHROW(test.SaveStatistics(x, device_statistics)); + REQUIRE(device_statistics.bytes_received() == 128 * nmodules * JUNGFRAU_PACKET_SIZE_BYTES); + + auto imageBuf = test.GetFrameBuffer(0, 0); + REQUIRE(memcmp(imageBuf, frame.data(), RAW_MODULE_SIZE * sizeof(uint16_t)) == 0); + + auto integration_result = test.GetIntegrationResult(0, 0); + CHECK(integration_result[0].sum == 32754LU * (RAW_MODULE_SIZE / 2 - 1)); + CHECK(integration_result[0].count == RAW_MODULE_SIZE / 2 - 1); + CHECK(integration_result[1].sum == 0); + CHECK(integration_result[1].count == 0); + CHECK(integration_result[FPGA_INTEGRATION_BIN_COUNT - 1].sum == 32754LU * (RAW_MODULE_SIZE / 2 - 2)); + CHECK(integration_result[FPGA_INTEGRATION_BIN_COUNT - 1].count == RAW_MODULE_SIZE / 2 - 2); + + integration_result = test.GetIntegrationResult(0, 1); + CHECK(integration_result[54].sum == 32754 * (RAW_MODULE_SIZE - 2)); + CHECK(integration_result[54].count == RAW_MODULE_SIZE - 2); + + integration_result = test.GetIntegrationResult(0, 2); + CHECK(integration_result[54].sum == 32754 * (RAW_MODULE_SIZE - 2)); + CHECK(integration_result[54].count == RAW_MODULE_SIZE - 2); + + integration_result = test.GetIntegrationResult(0, 3); + CHECK(integration_result[54].sum == 32754 * (RAW_MODULE_SIZE - 2)); + CHECK(integration_result[54].count == RAW_MODULE_SIZE - 2); +} \ No newline at end of file