// Copyright (2019-2023) Paul Scherrer Institute #include #include #include "../jungfrau/JFPedestalCalc.h" #include "../acquisition_device/HLSSimulatedDevice.h" #include "FPGAUnitTest.h" using namespace std::literals::chrono_literals; TEST_CASE("HLS_C_Simulation_internal_packet_generator", "[FPGA][Full]") { const uint16_t nmodules = 4; DiffractionExperiment x((DetectorGeometry(nmodules))); x.Mode(DetectorMode::Raw); x.UseInternalPacketGenerator(true).ImagesPerTrigger(4).PedestalG0Frames(0); HLSSimulatedDevice test(0, 64); std::vector ref_data(RAW_MODULE_SIZE); for (int i = 0; i < RAW_MODULE_SIZE; i++) ref_data[i] = i % 65536; for (int m = 0; m < nmodules; m++) test.SetInternalGeneratorFrame(ref_data.data(), m); REQUIRE_NOTHROW(test.StartAction(x)); REQUIRE_NOTHROW(test.WaitForActionComplete()); REQUIRE(test.OutputStream().size() == 1); REQUIRE(test.GetBytesReceived() == 128 * nmodules * 4 * JUNGFRAU_PACKET_SIZE_BYTES); for (int image = 0; image < 4; image++) { for (int m = 0; m < nmodules; m++) { auto imageBuf = (uint16_t *) test.GetDeviceOutput(image, m)->pixels; for (int i = 0; i < RAW_MODULE_SIZE; i++) REQUIRE(imageBuf[i] == i % 65536); } } REQUIRE(test.GetExpectedDescriptorsPerModule() == DMA_DESCRIPTORS_PER_MODULE); } TEST_CASE("HLS_C_Simulation_internal_packet_generator_custom_frame", "[FPGA][Full]") { const uint16_t nmodules = 32; const size_t nframes = 2; DiffractionExperiment x((DetectorGeometry(nmodules))); std::vector test_frame(nmodules*RAW_MODULE_SIZE); std::mt19937 g1(1387); std::uniform_int_distribution dist(0, 65535); for (auto &i: test_frame) i = dist(g1); x.Mode(DetectorMode::Raw); x.UseInternalPacketGenerator(true).ImagesPerTrigger(nframes).PedestalG0Frames(0); HLSSimulatedDevice test(0, 128); for (int m = 0; m < x.GetModulesNum(); m++) test.SetInternalGeneratorFrame(test_frame.data() + RAW_MODULE_SIZE * m, m); REQUIRE_NOTHROW(test.StartAction(x)); REQUIRE_NOTHROW(test.WaitForActionComplete()); REQUIRE(test.OutputStream().size() == 1); REQUIRE(test.GetBytesReceived() == 128 * nmodules * nframes * JUNGFRAU_PACKET_SIZE_BYTES); for (int image = 0; image < nframes; image++) { for (int m = 0; m < nmodules; m++) { REQUIRE(test.GetDeviceOutput(image, m)->module_statistics.timestamp == INT_PKT_GEN_EXPTTIME * image); REQUIRE(test.GetDeviceOutput(image, m)->module_statistics.pulse_id == INT_PKT_GEN_BUNCHID + image); REQUIRE(test.GetDeviceOutput(image, m)->module_statistics.exptime == INT_PKT_GEN_EXPTTIME); REQUIRE(test.GetDeviceOutput(image, m)->module_statistics.detector_type == SLS_DETECTOR_TYPE_JUNGFRAU); auto imageBuf = (uint16_t *) test.GetDeviceOutput(image, m)->pixels; for (int i = 0; i < RAW_MODULE_SIZE; i++) { REQUIRE(imageBuf[i] == test_frame[m * RAW_MODULE_SIZE + i]); } } } } TEST_CASE("HLS_C_Simulation_check_raw", "[FPGA][Full]") { std::vector raw_frames(RAW_MODULE_SIZE*20); for (int i = 0; i < 20; i++) { LoadBinaryFile("../../tests/test_data/mod5_raw" + std::to_string(i)+".bin", raw_frames.data() + i * RAW_MODULE_SIZE, RAW_MODULE_SIZE); } const uint16_t nmodules = 4; DiffractionExperiment x((DetectorGeometry(nmodules))); uint16_t data[4096]; x.Mode(DetectorMode::Raw); x.PedestalG0Frames(0).ImagesPerTrigger(5).NumTriggers(1); HLSSimulatedDevice test(0, 64); test.CreateJFPackets(x, 1, 5, 0, raw_frames.data()); test.CreateFinalPacket(x); REQUIRE_NOTHROW(test.StartAction(x)); REQUIRE_NOTHROW(test.WaitForActionComplete()); REQUIRE(test.Counters().GetSlowestFrameNumber() == 0); REQUIRE_NOTHROW(test.OutputStream().read()); REQUIRE(test.OutputStream().size() == 0); REQUIRE(test.GetBytesReceived() == 5 * 128 * JUNGFRAU_PACKET_SIZE_BYTES); uint64_t diffs = 0; for (int image = 0; image < 5; image++) { for (int j = 0; j < RAW_MODULE_SIZE; j++) { if (raw_frames[image*RAW_MODULE_SIZE+j] != ((uint16_t *) test.GetDeviceOutput(image, 0)->pixels)[j]) { diffs++; std::cout << raw_frames[image*RAW_MODULE_SIZE+j] << " " << ((uint16_t *) test.GetDeviceOutput(image, 0)->pixels)[j] << std::endl; } } } REQUIRE(diffs == 0); } TEST_CASE("HLS_C_Simulation_check_cancel", "[FPGA][Full]") { const uint16_t nmodules = 4; DiffractionExperiment x((DetectorGeometry(nmodules))); uint16_t data[4096]; x.Mode(DetectorMode::Raw); x.PedestalG0Frames(0).ImagesPerTrigger(5).NumTriggers(1); HLSSimulatedDevice test(0, 64); REQUIRE_NOTHROW(test.StartAction(x)); test.Cancel(); REQUIRE_NOTHROW(test.WaitForActionComplete()); REQUIRE(test.Counters().GetSlowestFrameNumber() == 0); REQUIRE_NOTHROW(test.OutputStream().read()); REQUIRE(test.OutputStream().size() == 0); REQUIRE(test.GetBytesReceived() == 0); } TEST_CASE("HLS_C_Simulation_check_cancel_conversion", "[FPGA][Full]") { const uint16_t nmodules = 4; DiffractionExperiment x((DetectorGeometry(nmodules))); uint16_t data[4096]; x.Mode(DetectorMode::Conversion); x.PedestalG0Frames(0).ImagesPerTrigger(5).NumTriggers(1); HLSSimulatedDevice test(0, 64); REQUIRE_NOTHROW(test.StartAction(x)); test.Cancel(); REQUIRE_NOTHROW(test.WaitForActionComplete()); REQUIRE(test.Counters().GetSlowestFrameNumber() == 0); REQUIRE_NOTHROW(test.OutputStream().read()); REQUIRE(test.OutputStream().size() == 0); REQUIRE(test.GetBytesReceived() == 0); } TEST_CASE("HLS_C_Simulation_check_delay", "[FPGA][Full]") { std::vector raw_frames(RAW_MODULE_SIZE*20); const uint16_t nmodules = 4; DiffractionExperiment x((DetectorGeometry(nmodules))); uint16_t data[4096]; x.Mode(DetectorMode::Raw); x.PedestalG0Frames(0).ImagesPerTrigger(3).NumTriggers(1); HLSSimulatedDevice test(0, 64); test.CreateJFPacket(x, 1, 0, 0, data); test.CreateJFPacket(x, 1, 0, 1, data); test.CreateJFPacket(x, 1, 0, 2, data); test.CreateJFPacket(x, 1, 0, 3, data); test.CreateJFPacket(x, 2, 0, 0, data); test.CreateJFPacket(x, 2, 0, 1, data); test.CreateJFPacket(x, 2, 0, 2, data); test.CreateJFPacket(x, 2, 0, 3, data); test.CreateJFPacket(x, 3, 0, 0, data); test.CreateJFPacket(x, 3, 0, 1, data); test.CreateJFPacket(x, 3, 0, 2, data); test.CreateJFPacket(x, 3, 0, 3, data); test.CreateFinalPacket(x); REQUIRE_NOTHROW(test.StartAction(x)); REQUIRE_NOTHROW(test.WaitForActionComplete()); REQUIRE(test.Counters().CalculateDelay(0) == 2); REQUIRE(test.Counters().CalculateDelay(0, 0) == 2); REQUIRE(test.Counters().CalculateDelay(1) == 1); REQUIRE(test.Counters().CalculateDelay(1, 0) == 1); REQUIRE(test.Counters().CalculateDelay(2) == 0); REQUIRE(test.Counters().CalculateDelay(2, 0) == 0); } TEST_CASE("HLS_C_Simulation_check_lost_frame_raw", "[FPGA][Full]") { std::vector raw_frames(RAW_MODULE_SIZE*20); const uint16_t nmodules = 4; DiffractionExperiment x((DetectorGeometry(nmodules))); uint16_t data[4096]; for (int i = 0; i < 4096; i++) data[i] = i; x.Mode(DetectorMode::Raw); x.PedestalG0Frames(0).ImagesPerTrigger(3).NumTriggers(1); HLSSimulatedDevice test(0, 64); test.CreateJFPacket(x, 1, 0, 0, data); test.CreateFinalPacket(x); REQUIRE_NOTHROW(test.StartAction(x)); REQUIRE_NOTHROW(test.WaitForActionComplete()); REQUIRE_NOTHROW(test.OutputStream().read()); REQUIRE(test.OutputStream().size() == 0); REQUIRE(test.GetBytesReceived() == JUNGFRAU_PACKET_SIZE_BYTES); REQUIRE(test.GetDeviceOutput(0,0)->pixels[0] == 0); REQUIRE(test.GetDeviceOutput(0,0)->pixels[1] == 1); REQUIRE(test.GetDeviceOutput(0,0)->pixels[4095] == 4095); REQUIRE_THROWS(test.GetDeviceOutput(0,1)); REQUIRE_THROWS(test.GetDeviceOutput(0,1)); } TEST_CASE("HLS_C_Simulation_check_lost_frame_conversion", "[FPGA][Full]") { std::vector raw_frames(RAW_MODULE_SIZE*20); const uint16_t nmodules = 4; DiffractionExperiment x((DetectorGeometry(nmodules))); uint16_t data[4096]; for (int i = 0; i < 4096; i++) data[i] = i; x.Mode(DetectorMode::Conversion); x.PedestalG0Frames(0).ImagesPerTrigger(3).NumTriggers(1); HLSSimulatedDevice test(0, 64); test.CreateJFPacket(x, 1, 0, 0, data); test.CreateFinalPacket(x); REQUIRE_NOTHROW(test.StartAction(x)); REQUIRE_NOTHROW(test.WaitForActionComplete()); REQUIRE_NOTHROW(test.OutputStream().read()); REQUIRE(test.OutputStream().size() == 0); REQUIRE(test.GetBytesReceived() == JUNGFRAU_PACKET_SIZE_BYTES); REQUIRE_THROWS(test.GetDeviceOutput(0,1)); REQUIRE_THROWS(test.GetDeviceOutput(0,1)); REQUIRE_THROWS(test.GetDeviceOutput(1,0)); REQUIRE_THROWS(test.GetDeviceOutput(2,1)); } TEST_CASE("HLS_C_Simulation_check_single_packet", "[FPGA][Full]") { std::vector raw_frames(RAW_MODULE_SIZE*20); const uint16_t nmodules = 4; DiffractionExperiment x((DetectorGeometry(nmodules))); uint16_t data[4096]; uint16_t wrong[4096]; for (int i = 0; i < 4096; i++) { data[i] = (7 * i + 534 + 5 * i * i) % UINT16_MAX; wrong[i] = UINT16_MAX; } x.Mode(DetectorMode::Raw); x.PedestalG0Frames(0).ImagesPerTrigger(3).NumTriggers(1); HLSSimulatedDevice test(0, 64); test.CreateJFPacket(x, 1, 0, 0, data); test.CreateJFPacket(x, 1, 64, 0, data); test.CreateJFPacket(x, 1, 0, 2, data); test.CreateJFPacket(x, 1, 2, 3, data); test.CreateJFPacket(x, 1, 3, 3, data); test.CreateJFPacket(x, 1, 1, 3, data); test.CreateJFPacket(x, 1, 0, 3, data); test.CreateJFPacket(x, 1, 64, 3, data); test.CreateJFPacket(x, 1, 5, 0, data); test.CreateJFPacket(x, 1, 4, 0, data); test.CreateJFPacket(x, 1, 67, 1, data); test.CreateJFPacket(x, 1, 66, 1, data); test.CreateJFPacket(x, 1, 68, 1, data); test.CreateJFPacket(x, 3, 1, 0, data); test.CreateJFPacket(x, 2, 1, 0, data); test.CreateJFPacket(x, 4, 1, 0, data); test.CreateFinalPacket(x); REQUIRE_NOTHROW(test.StartAction(x)); REQUIRE_NOTHROW(test.WaitForActionComplete()); REQUIRE_NOTHROW(test.OutputStream().read()); REQUIRE(test.OutputStream().size() == 0); REQUIRE(test.GetBytesReceived() == 15 * JUNGFRAU_PACKET_SIZE_BYTES); REQUIRE(memcmp(test.GetDeviceOutput(0,0)->pixels, data, JUNGFRAU_PACKET_SIZE_BYTES) == 0); REQUIRE(memcmp(test.GetDeviceOutput(0,0)->pixels + 1 * JUNGFRAU_PACKET_SIZE_BYTES/2, wrong, JUNGFRAU_PACKET_SIZE_BYTES) == 0); REQUIRE(memcmp(test.GetDeviceOutput(0,0)->pixels + 2 * JUNGFRAU_PACKET_SIZE_BYTES/2, wrong, JUNGFRAU_PACKET_SIZE_BYTES) == 0); REQUIRE(memcmp(test.GetDeviceOutput(0,0)->pixels + 3 * JUNGFRAU_PACKET_SIZE_BYTES/2, wrong, JUNGFRAU_PACKET_SIZE_BYTES) == 0); REQUIRE(memcmp(test.GetDeviceOutput(0,0)->pixels + 4 * JUNGFRAU_PACKET_SIZE_BYTES/2, data, JUNGFRAU_PACKET_SIZE_BYTES) == 0); REQUIRE(memcmp(test.GetDeviceOutput(0,0)->pixels + 5 * JUNGFRAU_PACKET_SIZE_BYTES/2, data, JUNGFRAU_PACKET_SIZE_BYTES) == 0); REQUIRE(memcmp(test.GetDeviceOutput(0,0)->pixels + 6 * JUNGFRAU_PACKET_SIZE_BYTES/2, wrong, JUNGFRAU_PACKET_SIZE_BYTES) == 0); REQUIRE(memcmp(test.GetDeviceOutput(0,0)->pixels + 64 * JUNGFRAU_PACKET_SIZE_BYTES/2, data, JUNGFRAU_PACKET_SIZE_BYTES) == 0); REQUIRE(memcmp(test.GetDeviceOutput(0,1)->pixels + 67 * JUNGFRAU_PACKET_SIZE_BYTES/2, data, JUNGFRAU_PACKET_SIZE_BYTES) == 0); REQUIRE(memcmp(test.GetDeviceOutput(0,1)->pixels + 65 * JUNGFRAU_PACKET_SIZE_BYTES/2, wrong, JUNGFRAU_PACKET_SIZE_BYTES) == 0); REQUIRE(test.GetDeviceOutput(0,0)->module_statistics.detector_type == SLS_DETECTOR_TYPE_JUNGFRAU); } TEST_CASE("HLS_C_Simulation_check_convert_full_range", "[FPGA][Full]") { Logger logger("HLS_C_Simulation_check_convert_full_range"); std::vector data(RAW_MODULE_SIZE); std::vector gain(3 * RAW_MODULE_SIZE); JFModulePedestal pedestal_g0(0), pedestal_g1(14500), pedestal_g2(14500); for (int i = 0; i < RAW_MODULE_SIZE; i++) { data[i] = i % UINT16_MAX; } std::vector energy_values = {6.0, 12.4, 17.7, 5, 4.5, 3.7}; const uint16_t nmodules = 1; DiffractionExperiment x((DetectorGeometry(nmodules))); x.Mode(DetectorMode::Conversion); HLSSimulatedDevice test(0, 64); auto gain_from_file = GainCalibrationFromTestFile(); for (const auto energy : energy_values) { x.PedestalG0Frames(0).NumTriggers(1).ImagesPerTrigger(1).PhotonEnergy_keV(energy); REQUIRE(x.GetPhotonEnergy_keV() == Approx(energy)); JFCalibration c_in(x); c_in.Pedestal(0,0) = pedestal_g0; c_in.Pedestal(0,1) = pedestal_g1; c_in.Pedestal(0,2) = pedestal_g2; for (int i = 0; i < x.GetModulesNum(); i++) c_in.GainCalibration(i) = gain_from_file; test.InitializeCalibration(x, c_in); test.CreateJFPackets(x, 1, 1, 0, data.data()); test.CreateFinalPacket(x); REQUIRE_NOTHROW(test.StartAction(x)); REQUIRE_NOTHROW(test.WaitForActionComplete()); REQUIRE_NOTHROW(test.OutputStream().read()); REQUIRE(test.OutputStream().size() == 0); CHECK(test.GetBytesReceived() == 128 * JUNGFRAU_PACKET_SIZE_BYTES); double mean_error = CheckConversion(x, c_in, data.data(), test.GetDeviceOutput(0,0)->pixels); logger.Info("Error of {:.2f} for photon energy {} keV", mean_error, energy); REQUIRE(mean_error < 0.5); } } TEST_CASE("HLS_C_Simulation_check_convert_full_range_HG0", "[FPGA][Full]") { Logger logger("HLS_C_Simulation_check_convert_full_range_HG0"); std::vector data(RAW_MODULE_SIZE); std::vector gain(3 * RAW_MODULE_SIZE); JFModulePedestal pedestal_g0(1000), pedestal_g1(14500), pedestal_g2(14500); for (int i = 0; i < RAW_MODULE_SIZE; i++) { data[i] = i % 0x4000; // only generate gain 0 } std::vector energy_values = {6.0, 12.4, 17.7, 5, 4.5, 3.7, 2.0, 1.0, 0.5, 0.1}; const uint16_t nmodules = 1; DiffractionExperiment x((DetectorGeometry(nmodules))); x.Mode(DetectorMode::Conversion).UsingGainHG0(true); HLSSimulatedDevice test(0, 64); auto gain_from_file = GainCalibrationFromTestFile(); logger.Info("With HG0"); for (const auto energy : energy_values) { x.PedestalG0Frames(0).NumTriggers(1).ImagesPerTrigger(1).PhotonEnergy_keV(energy); REQUIRE(x.IsUsingGainHG0()); REQUIRE(x.GetPhotonEnergy_keV() == Approx(energy)); JFCalibration c_in(x); c_in.Pedestal(0,0) = pedestal_g0; c_in.Pedestal(0,1) = pedestal_g1; c_in.Pedestal(0,2) = pedestal_g2; for (int i = 0; i < x.GetModulesNum(); i++) c_in.GainCalibration(i) = gain_from_file; test.InitializeCalibration(x, c_in); test.CreateJFPackets(x, 1, 1, 0, data.data()); test.CreateFinalPacket(x); REQUIRE_NOTHROW(test.StartAction(x)); REQUIRE_NOTHROW(test.WaitForActionComplete()); REQUIRE_NOTHROW(test.OutputStream().read()); REQUIRE(test.OutputStream().size() == 0); CHECK(test.GetBytesReceived() == 128 * JUNGFRAU_PACKET_SIZE_BYTES); double mean_error = CheckConversion(x, c_in, data.data(), test.GetDeviceOutput(0,0)->pixels); logger.Info(" std. dev. of {:.2f} for photon energy {} keV", mean_error, energy); REQUIRE(mean_error < 0.5); } logger.Info("Without HG0"); x.UsingGainHG0(false); for (const auto energy : energy_values) { x.PedestalG0Frames(0).NumTriggers(1).ImagesPerTrigger(1).PhotonEnergy_keV(energy); REQUIRE(!x.IsUsingGainHG0()); REQUIRE(x.GetPhotonEnergy_keV() == Approx(energy)); JFCalibration c_in(x); c_in.Pedestal(0,0) = pedestal_g0; c_in.Pedestal(0,1) = pedestal_g1; c_in.Pedestal(0,2) = pedestal_g2; for (int i = 0; i < x.GetModulesNum(); i++) c_in.GainCalibration(i) = gain_from_file; test.InitializeCalibration(x, c_in); test.CreateJFPackets(x, 1, 1, 0, data.data()); test.CreateFinalPacket(x); REQUIRE_NOTHROW(test.StartAction(x)); REQUIRE_NOTHROW(test.WaitForActionComplete()); REQUIRE_NOTHROW(test.OutputStream().read()); REQUIRE(test.OutputStream().size() == 0); CHECK(test.GetBytesReceived() == 128 * JUNGFRAU_PACKET_SIZE_BYTES); double mean_error = CheckConversion(x, c_in, data.data(), test.GetDeviceOutput(0,0)->pixels); logger.Info(" std. dev. of {:.2f} for photon energy {} keV", mean_error, energy); REQUIRE(mean_error < 0.5); } } TEST_CASE("HLS_C_Simulation_check_convert_full_range_fixedG1", "[FPGA][Full]") { Logger logger("HLS_C_Simulation_check_convert_full_range_fixedG1"); std::vector data(RAW_MODULE_SIZE); std::vector gain(3 * RAW_MODULE_SIZE); JFModulePedestal pedestal_g0(1000), pedestal_g1(1500), pedestal_g2(14500); std::vector energy_values = {6.0, 12.4, 17.7, 5, 4.5, 3.7, 2.0, 1.0}; for (int i = 0; i < RAW_MODULE_SIZE; i++) { data[i] = i % UINT16_MAX; } const uint16_t nmodules = 1; DiffractionExperiment x((DetectorGeometry(nmodules))); x.Mode(DetectorMode::Conversion).FixedGainG1(true); HLSSimulatedDevice test(0, 64); auto gain_from_file = GainCalibrationFromTestFile(); for (const auto energy : energy_values) { x.PedestalG0Frames(0).NumTriggers(1).ImagesPerTrigger(1).PhotonEnergy_keV(energy); REQUIRE(x.IsFixedGainG1()); REQUIRE(x.GetPhotonEnergy_keV() == Approx(energy)); JFCalibration c_in(x); c_in.Pedestal(0,0) = pedestal_g0; c_in.Pedestal(0,1) = pedestal_g1; c_in.Pedestal(0,2) = pedestal_g2; for (int i = 0; i < x.GetModulesNum(); i++) c_in.GainCalibration(i) = gain_from_file; test.InitializeCalibration(x, c_in); test.CreateJFPackets(x, 1, 1, 0, data.data()); test.CreateFinalPacket(x); REQUIRE_NOTHROW(test.StartAction(x)); REQUIRE_NOTHROW(test.WaitForActionComplete()); REQUIRE_NOTHROW(test.OutputStream().read()); REQUIRE(test.OutputStream().size() == 0); CHECK(test.GetBytesReceived() == 128 * JUNGFRAU_PACKET_SIZE_BYTES); double mean_error = CheckConversion(x, c_in, data.data(), test.GetDeviceOutput(0,0)->pixels); logger.Info(" std. dev. of {:.2f} for photon energy {} keV", mean_error, energy); REQUIRE(mean_error < 0.5); } } TEST_CASE("HLS_C_Simulation_check_convert_full_range_I32", "[FPGA][Full]") { Logger logger("HLS_C_Simulation_check_convert_full_range_I32"); std::vector data(RAW_MODULE_SIZE); std::vector gain(3 * RAW_MODULE_SIZE); JFModulePedestal pedestal_g0(0), pedestal_g1(14500), pedestal_g2(14500); for (int i = 0; i < RAW_MODULE_SIZE; i++) { data[i] = i % UINT16_MAX; } std::vector energy_values = {6.0, 12.4, 17.7, 5, 4.5, 3.7, 3.0}; const uint16_t nmodules = 1; DiffractionExperiment x((DetectorGeometry(nmodules))); x.Mode(DetectorMode::Conversion); HLSSimulatedDevice test(0, 64); auto gain_from_file = GainCalibrationFromTestFile(); for (const auto energy : energy_values) { x.PedestalG0Frames(0).NumTriggers(1).ImagesPerTrigger(1).PhotonEnergy_keV(energy).FPGAOutputMode(FPGAPixelOutput::Int32); REQUIRE(x.GetPhotonEnergy_keV() == Approx(energy)); JFCalibration c_in(x); c_in.Pedestal(0,0) = pedestal_g0; c_in.Pedestal(0,1) = pedestal_g1; c_in.Pedestal(0,2) = pedestal_g2; for (int i = 0; i < x.GetModulesNum(); i++) c_in.GainCalibration(i) = gain_from_file; test.InitializeCalibration(x, c_in); test.CreateJFPackets(x, 1, 1, 0, data.data()); test.CreateFinalPacket(x); REQUIRE_NOTHROW(test.StartAction(x)); REQUIRE_NOTHROW(test.WaitForActionComplete()); REQUIRE_NOTHROW(test.OutputStream().read()); REQUIRE(test.OutputStream().size() == 0); CHECK(test.GetBytesReceived() == 128 * JUNGFRAU_PACKET_SIZE_BYTES); double mean_error = CheckConversion(x, c_in, data.data(), (int32_t *) test.GetDeviceOutput(0,0)->pixels); logger.Info("Error of {:.2f} for photon energy {} keV", mean_error, energy); REQUIRE(mean_error < 0.5); } } TEST_CASE("HLS_C_Simulation_check_convert_full_range_sum4", "[FPGA][Full]") { Logger logger("HLS_C_Simulation_check_convert_full_range_sum4"); std::vector data(RAW_MODULE_SIZE); std::vector gain(3 * RAW_MODULE_SIZE); JFModulePedestal pedestal_g0(0), pedestal_g1(14500), pedestal_g2(14500); for (int i = 0; i < RAW_MODULE_SIZE; i++) { data[i] = i % UINT16_MAX; } std::vector energy_values = {6.0, 12.4, 17.7, 5, 4.5, 3.7}; const uint16_t nmodules = 1; DiffractionExperiment x((DetectorGeometry(nmodules))); x.Mode(DetectorMode::Conversion); HLSSimulatedDevice test(0, 64); auto gain_from_file = GainCalibrationFromTestFile(); size_t nsummation = 4; for (const auto energy : energy_values) { logger.Info("Trying with {} keV", energy); x.PedestalG0Frames(0).NumTriggers(1).ImagesPerTrigger(1).PhotonEnergy_keV(energy).Summation(nsummation); REQUIRE(x.GetPhotonEnergy_keV() == Approx(energy)); JFCalibration c_in(x); c_in.Pedestal(0,0) = pedestal_g0; c_in.Pedestal(0,1) = pedestal_g1; c_in.Pedestal(0,2) = pedestal_g2; for (int i = 0; i < x.GetModulesNum(); i++) c_in.GainCalibration(i) = gain_from_file; test.InitializeCalibration(x, c_in); for (int i = 0; i < nsummation; i++) test.CreateJFPackets(x, i + 1, 1, 0, data.data()); test.CreateFinalPacket(x); REQUIRE_NOTHROW(test.StartAction(x)); REQUIRE_NOTHROW(test.WaitForActionComplete()); REQUIRE_NOTHROW(test.OutputStream().read()); REQUIRE(test.OutputStream().size() == 0); CHECK(test.GetBytesReceived() == 128 * nsummation * JUNGFRAU_PACKET_SIZE_BYTES); double mean_error = CheckConversion(x, c_in, data.data(), (int32_t *) test.GetDeviceOutput(0,0)->pixels); REQUIRE(mean_error < 2.0); } } TEST_CASE("HLS_C_Simulation_check_convert_full_range_U16", "[FPGA][Full]") { Logger logger("HLS_C_Simulation_check_convert_full_range_U16"); std::vector data(RAW_MODULE_SIZE); std::vector gain(3 * RAW_MODULE_SIZE); JFModulePedestal pedestal_g0(0), pedestal_g1(14500), pedestal_g2(14500); for (int i = 0; i < RAW_MODULE_SIZE; i++) { data[i] = i % UINT16_MAX; } std::vector energy_values = {6.0, 12.4, 17.7, 5, 4.5, 3.7}; const uint16_t nmodules = 1; DiffractionExperiment x((DetectorGeometry(nmodules))); x.Mode(DetectorMode::Conversion); HLSSimulatedDevice test(0, 64); auto gain_from_file = GainCalibrationFromTestFile(); for (const auto energy : energy_values) { logger.Info("Trying with {} keV", energy); x.PedestalG0Frames(0).NumTriggers(1).ImagesPerTrigger(1).PhotonEnergy_keV(energy).FPGAOutputMode(FPGAPixelOutput::Uint16); REQUIRE(x.GetPhotonEnergy_keV() == Approx(energy)); JFCalibration c_in(x); c_in.Pedestal(0,0) = pedestal_g0; c_in.Pedestal(0,1) = pedestal_g1; c_in.Pedestal(0,2) = pedestal_g2; for (int i = 0; i < x.GetModulesNum(); i++) c_in.GainCalibration(i) = gain_from_file; test.InitializeCalibration(x, c_in); test.CreateJFPackets(x, 1, 1, 0, data.data()); test.CreateFinalPacket(x); REQUIRE_NOTHROW(test.StartAction(x)); REQUIRE_NOTHROW(test.WaitForActionComplete()); REQUIRE_NOTHROW(test.OutputStream().read()); REQUIRE(test.OutputStream().size() == 0); CHECK(test.GetBytesReceived() == 128 * JUNGFRAU_PACKET_SIZE_BYTES); double mean_error = CheckConversion(x, c_in, data.data(), (uint16_t *) test.GetDeviceOutput(0,0)->pixels); REQUIRE(mean_error < 0.5); } } TEST_CASE("HLS_C_Simulation_no_conversion_U16", "[FPGA][Full]") { Logger logger("HLS_C_Simulation_no_conversion_U16"); std::vector data(RAW_MODULE_SIZE); for (int i = 0; i < RAW_MODULE_SIZE; i++) data[i] = i % UINT16_MAX; data[5456] = UINT16_MAX; data[211] = UINT16_MAX; const uint16_t nmodules = 1; DiffractionExperiment x((DetectorGeometry(nmodules))); x.Mode(DetectorMode::Conversion).ConversionOnFPGA(false); HLSSimulatedDevice test(0, 64); x.PedestalG0Frames(0).NumTriggers(1).ImagesPerTrigger(1).FPGAOutputMode(FPGAPixelOutput::Uint16); test.CreateJFPackets(x, 1, 1, 0, data.data()); test.CreateFinalPacket(x); REQUIRE_NOTHROW(test.StartAction(x)); REQUIRE_NOTHROW(test.WaitForActionComplete()); REQUIRE_NOTHROW(test.OutputStream().read()); REQUIRE(test.OutputStream().size() == 0); CHECK(test.GetBytesReceived() == 128 * JUNGFRAU_PACKET_SIZE_BYTES); auto output = (uint16_t *) test.GetDeviceOutput(0, 0)->pixels; size_t err = 0; for (int i = 0; i < RAW_MODULE_SIZE; i++) { CHECK(data[i] == output[i]); } REQUIRE(err == 0); } TEST_CASE("HLS_C_Simulation_no_conversion_U32", "[FPGA][Full]") { Logger logger("HLS_C_Simulation_no_conversion_U32"); std::vector data(RAW_MODULE_SIZE); for (int i = 0; i < RAW_MODULE_SIZE; i++) data[i] = i % UINT16_MAX; data[5456] = UINT16_MAX; data[211] = UINT16_MAX; const uint16_t nmodules = 1; DiffractionExperiment x((DetectorGeometry(nmodules))); x.Mode(DetectorMode::Conversion).ConversionOnFPGA(false); HLSSimulatedDevice test(0, 64); x.PedestalG0Frames(0).NumTriggers(1).ImagesPerTrigger(1).FPGAOutputMode(FPGAPixelOutput::Uint32); test.CreateJFPackets(x, 1, 1, 0, data.data()); test.CreateFinalPacket(x); REQUIRE_NOTHROW(test.StartAction(x)); REQUIRE_NOTHROW(test.WaitForActionComplete()); REQUIRE_NOTHROW(test.OutputStream().read()); REQUIRE(test.OutputStream().size() == 0); CHECK(test.GetBytesReceived() == 128 * JUNGFRAU_PACKET_SIZE_BYTES); auto output = (uint32_t *) test.GetDeviceOutput(0, 0)->pixels; size_t err = 0; for (int i = 0; i < RAW_MODULE_SIZE; i++) { if (data[i] == UINT16_MAX) { CHECK(output[i] == UINT32_MAX); } else if (data[i] != output[i]) err++; } REQUIRE(err == 0); } TEST_CASE("HLS_C_Simulation_no_conversion_I32", "[FPGA][Full]") { Logger logger("HLS_C_Simulation_no_conversion_I32"); std::vector data(RAW_MODULE_SIZE); for (int i = 0; i < RAW_MODULE_SIZE; i++) data[i] = i % UINT16_MAX; data[5456] = UINT16_MAX; data[211] = UINT16_MAX; const uint16_t nmodules = 1; DiffractionExperiment x((DetectorGeometry(nmodules))); x.Mode(DetectorMode::Conversion).ConversionOnFPGA(false); HLSSimulatedDevice test(0, 64); x.PedestalG0Frames(0).NumTriggers(1).ImagesPerTrigger(1).FPGAOutputMode(FPGAPixelOutput::Int32); test.CreateJFPackets(x, 1, 1, 0, data.data()); test.CreateFinalPacket(x); REQUIRE_NOTHROW(test.StartAction(x)); REQUIRE_NOTHROW(test.WaitForActionComplete()); REQUIRE_NOTHROW(test.OutputStream().read()); REQUIRE(test.OutputStream().size() == 0); CHECK(test.GetBytesReceived() == 128 * JUNGFRAU_PACKET_SIZE_BYTES); auto data16_signed = (int16_t *) data.data(); auto output = (int32_t *) test.GetDeviceOutput(0, 0)->pixels; size_t err = 0; for (int i = 0; i < RAW_MODULE_SIZE; i++) { if (data16_signed[i] == INT16_MAX) { CHECK(output[i] == INT32_MAX); } else if (data16_signed[i] == INT16_MIN) { CHECK(output[i] == INT32_MIN); } else if (data16_signed[i] != output[i]) err++; } REQUIRE(err == 0); } TEST_CASE("HLS_C_Simulation_internal_packet_generator_convert_full_range", "[FPGA][Full]") { double energy = 6.0; const uint16_t nmodules = 4; DiffractionExperiment x((DetectorGeometry(nmodules, 2, 8, 36, true))); std::vector data(RAW_MODULE_SIZE); JFModulePedestal pedestal_g0, pedestal_g1, pedestal_g2; for (int i = 0; i < RAW_MODULE_SIZE; i++) { pedestal_g0.GetPedestal()[i] = 0 + (i / 65536) * 1000 + 100 * (i % 5); pedestal_g1.GetPedestal()[i] = 14500 - (i / 65536) * 1000 + 100 * (i % 3); pedestal_g2.GetPedestal()[i] = 14500 - + (i / 65536) * 1000; } for (int i = 0; i < RAW_MODULE_SIZE; i++) { data[i] = i % RAW_MODULE_SIZE; } x.Mode(DetectorMode::Conversion); x.PedestalG0Frames(0).NumTriggers(1).ImagesPerTrigger(1).UseInternalPacketGenerator(true).PhotonEnergy_keV(energy); REQUIRE(x.GetPhotonEnergy_keV() == Approx(energy)); auto gain_from_file = GainCalibrationFromTestFile(); JFCalibration c(x); for (int i = 0; i < x.GetModulesNum(); i++) { c.Pedestal(i, 0) = pedestal_g0; c.Pedestal(i, 1) = pedestal_g1; c.Pedestal(i, 2) = pedestal_g2; c.GainCalibration(i) = gain_from_file; } HLSSimulatedDevice test(0, 64); std::vector ref_data(RAW_MODULE_SIZE); for (int i = 0; i < RAW_MODULE_SIZE; i++) ref_data[i] = i % 65536; for (int m = 0; m < nmodules; m++) test.SetInternalGeneratorFrame(ref_data.data(), m); REQUIRE_NOTHROW(test.InitializeCalibration(x, c)); REQUIRE_NOTHROW(test.StartAction(x)); REQUIRE_NOTHROW(test.WaitForActionComplete()); REQUIRE_NOTHROW(test.OutputStream().read()); REQUIRE(test.OutputStream().size() == 0); REQUIRE(test.GetBytesReceived() == nmodules * 128 * JUNGFRAU_PACKET_SIZE_BYTES); double mean_error = CheckConversion(x, c, data.data(), test.GetDeviceOutput(0,0)->pixels); REQUIRE(mean_error < 0.5); } TEST_CASE("HLS_C_Simulation_internal_packet_generator_convert_full_range_adu_histo", "[FPGA][Full]") { double energy = 6.0; const uint16_t nmodules = 4; DiffractionExperiment x((DetectorGeometry(nmodules, 2, 8, 36, true))); std::vector data(RAW_MODULE_SIZE); JFModulePedestal pedestal_g0, pedestal_g1, pedestal_g2; for (int i = 0; i < RAW_MODULE_SIZE; i++) { pedestal_g0.GetPedestal()[i] = 0 + (i / 65536) * 1000 + 100 * (i % 5); pedestal_g1.GetPedestal()[i] = 14500 - (i / 65536) * 1000 + 100 * (i % 3); pedestal_g2.GetPedestal()[i] = 14500 - + (i / 65536) * 1000; } for (int i = 0; i < RAW_MODULE_SIZE; i++) { data[i] = i % RAW_MODULE_SIZE; } x.Mode(DetectorMode::Conversion); x.PedestalG0Frames(0).NumTriggers(1).ImagesPerTrigger(1).UseInternalPacketGenerator(true).PhotonEnergy_keV(energy); REQUIRE(x.GetPhotonEnergy_keV() == Approx(energy)); auto gain_from_file = GainCalibrationFromTestFile(); JFCalibration c(x); for (int i = 0; i < x.GetModulesNum(); i++) { c.Pedestal(i, 0) = pedestal_g0; c.Pedestal(i, 1) = pedestal_g1; c.Pedestal(i, 2) = pedestal_g2; c.GainCalibration(i) = gain_from_file; } HLSSimulatedDevice test(0, 64); std::vector ref_data(RAW_MODULE_SIZE); for (int i = 0; i < RAW_MODULE_SIZE; i++) ref_data[i] = i % 65536; for (int m = 0; m < nmodules; m++) test.SetInternalGeneratorFrame(ref_data.data(), m); REQUIRE_NOTHROW(test.InitializeCalibration(x, c)); REQUIRE_NOTHROW(test.StartAction(x)); REQUIRE_NOTHROW(test.WaitForActionComplete()); REQUIRE_NOTHROW(test.OutputStream().read()); REQUIRE(test.OutputStream().size() == 0); REQUIRE(test.GetBytesReceived() == nmodules * 128 * JUNGFRAU_PACKET_SIZE_BYTES); uint32_t err = 0; const uint32_t *adu_histogram = test.GetDeviceOutput(0, 0)->adu_histogram; for (int i = 0; i < ADU_HISTO_BIN_COUNT; i++) { if(adu_histogram[i] != RAW_MODULE_SIZE / ADU_HISTO_BIN_COUNT) err++; } REQUIRE(err == 0); } TEST_CASE("HLS_C_Simulation_check_2_trigger_convert", "[FPGA][Full]") { std::vector pedestal_g0(RAW_MODULE_SIZE), pedestal_g1(RAW_MODULE_SIZE), pedestal_g2(RAW_MODULE_SIZE); LoadBinaryFile("../../tests/test_data/mod5_pedeG0.bin", pedestal_g0.data(), RAW_MODULE_SIZE); LoadBinaryFile("../../tests/test_data/mod5_pedeG1.bin", pedestal_g1.data(), RAW_MODULE_SIZE); LoadBinaryFile("../../tests/test_data/mod5_pedeG2.bin", pedestal_g2.data(), RAW_MODULE_SIZE); std::vector raw_frames(RAW_MODULE_SIZE*20); std::vector conv_frames(RAW_MODULE_SIZE*20); for (int i = 0; i < 20; i++) { LoadBinaryFile("../../tests/test_data/mod5_raw" + std::to_string(i)+".bin", raw_frames.data() + i * RAW_MODULE_SIZE, RAW_MODULE_SIZE); LoadBinaryFile("../../tests/test_data/mod5_conv" + std::to_string(i)+".bin", conv_frames.data() + i * RAW_MODULE_SIZE, RAW_MODULE_SIZE); } const uint16_t nmodules = 4; DiffractionExperiment x((DetectorGeometry(nmodules))); uint16_t data[4096]; x.Mode(DetectorMode::Conversion); x.PedestalG0Frames(0).NumTriggers(2).ImagesPerTrigger(5); HLSSimulatedDevice test(0, 64); JFCalibration c(x); REQUIRE_NOTHROW(c.Pedestal(0, 0).LoadPedestal(pedestal_g0)); REQUIRE_NOTHROW(c.Pedestal(0, 1).LoadPedestal(pedestal_g1)); REQUIRE_NOTHROW(c.Pedestal(0, 2).LoadPedestal(pedestal_g2)); REQUIRE_NOTHROW(c.GainCalibration(0) = GainCalibrationFromTestFile()); REQUIRE_NOTHROW(test.InitializeCalibration(x, c)); // send some frames without trigger (to be ignored) test.CreateJFPackets(x, 1, 10, 0, raw_frames.data()); test.CreateFinalPacket(x); REQUIRE_NOTHROW(test.StartAction(x)); REQUIRE(!test.Counters().IsAcquisitionFinished()); test.WaitForActionComplete(); REQUIRE(test.Counters().IsAcquisitionFinished()); // address properly aligned REQUIRE((uint64_t) test.GetDeviceOutput(0,0)->pixels % 128 == 0); REQUIRE(test.Counters().GetSlowestFrameNumber() == 0); REQUIRE(test.Counters().GetCurrFrameNumber(0) == 9); REQUIRE_NOTHROW(test.OutputStream().read()); REQUIRE(test.OutputStream().size() == 0); REQUIRE(test.GetBytesReceived()== 128 * 10 * JUNGFRAU_PACKET_SIZE_BYTES); double mean_error = 0.0; for (int image = 0; image < 10; image++) { auto img = test.GetDeviceOutput(image, 0)->pixels; for (int j = 0; j < RAW_MODULE_SIZE; j++) { if ((img[j] < 30000) && (img[j] > -30000)) { float diff = (conv_frames[image * RAW_MODULE_SIZE + j] - (float) img[j]); mean_error += diff * diff; } } } mean_error = sqrt(mean_error/ (10*RAW_MODULE_SIZE)); std::cout << "Mean error " << mean_error << std::endl; REQUIRE(mean_error < 0.30); } TEST_CASE("HLS_C_Simulation_check_detect_last_frame", "[FPGA][Full]") { const uint16_t nmodules = 4; DiffractionExperiment x((DetectorGeometry(nmodules))); uint16_t data[4096]; x.Mode(DetectorMode::Conversion); x.PedestalG0Frames(0).NumTriggers(2).ImagesPerTrigger(5); HLSSimulatedDevice test(0, 64); test.CreateJFPacket(x, 15, 0, 0, data); REQUIRE_NOTHROW(test.StartAction(x)); REQUIRE(!test.Counters().IsAcquisitionFinished()); test.WaitForActionComplete(); REQUIRE(test.Counters().IsAcquisitionFinished()); REQUIRE_NOTHROW(test.OutputStream().read()); REQUIRE(test.OutputStream().size() == 0); } TEST_CASE("HLS_C_Simulation_check_wrong_packet_size", "[FPGA][Full]") { const uint16_t nmodules = 1; DiffractionExperiment x((DetectorGeometry(nmodules))); uint16_t data[8192]; x.Mode(DetectorMode::Conversion); x.PedestalG0Frames(0).NumTriggers(1).ImagesPerTrigger(5); HLSSimulatedDevice test(0, 64); // send some frames with wrong size or tuser=1 test.CreateJFPacket(x, 1, 0, 0, data, 0); test.CreateJFPacket(x, 1, 1, 0, data, -1); test.CreateJFPacket(x, 1, 2, 0, data, 2); test.CreateJFPacket(x, 1, 3, 0, data, 0); test.CreateJFPacket(x, 1, 4, 0, data, -5); test.CreateJFPacket(x, 1, 5, 0, data, 0, 1); test.CreateJFPacket(x, 1, 6, 0, data, 0); test.CreateJFPacket(x, 1, 7, 0, data, 0); test.CreateJFPacket(x, 1, 8, 0, data, 7); test.CreateJFPacket(x, 1, 9, 0, data, 100); test.CreateJFPacket(x, 1, 10, 0, data, 2); test.CreateJFPacket(x, 1, 11, 0, data, 0); test.CreateJFPacket(x, 1, 12, 0, data, -80); test.CreateJFPacket(x, 1, 13, 0, data, 100); test.CreateJFPacket(x, 1, 118, 0, data, 0); test.CreateFinalPacket(x); REQUIRE_NOTHROW(test.StartAction(x)); REQUIRE(!test.Counters().IsAcquisitionFinished()); test.WaitForActionComplete(); REQUIRE(test.Counters().IsAcquisitionFinished()); REQUIRE(test.GetBytesReceived() == 6 * JUNGFRAU_PACKET_SIZE_BYTES); } TEST_CASE("HLS_DataCollectionFSM","[OpenCAPI]") { DataCollectionConfig act_reg; STREAM_512 raw0; STREAM_512 raw1; hls::stream addr0; hls::stream addr1; ap_uint<1> run_data_collection = 0; ap_uint<1> cancel_data_collection = 0; ap_uint<1> idle_data_collection; uint32_t save_data_collection_counter; act_reg.mode = MODE_CONV; // state = WAIT_FOR_START volatile rcv_state_t state; data_collection_fsm(raw0, raw1, addr0, addr1, run_data_collection, cancel_data_collection, idle_data_collection, act_reg.mode, act_reg.energy_kev, act_reg.nframes, act_reg.nmodules, act_reg.nstorage_cells, act_reg.nsummation, state); REQUIRE(idle_data_collection == 1); REQUIRE(addr1.empty()); REQUIRE(raw1.empty()); REQUIRE( state == RCV_WAIT_FOR_START); run_data_collection = 1; // state = WAIT_FOR_START data_collection_fsm(raw0, raw1, addr0, addr1, run_data_collection, cancel_data_collection, idle_data_collection, act_reg.mode, act_reg.energy_kev, act_reg.nframes, act_reg.nmodules, act_reg.nstorage_cells, act_reg.nsummation, state); REQUIRE(idle_data_collection == 0); REQUIRE(addr1.empty()); REQUIRE(raw1.empty()); REQUIRE( state == RCV_WAIT_FOR_START_LOW); // state = WAIT_FOR_START_LOW data_collection_fsm(raw0, raw1, addr0, addr1, run_data_collection, cancel_data_collection, idle_data_collection, act_reg.mode, act_reg.energy_kev, act_reg.nframes, act_reg.nmodules, act_reg.nstorage_cells, act_reg.nsummation, state); REQUIRE(idle_data_collection == 0); REQUIRE(addr1.empty()); REQUIRE(raw1.empty()); REQUIRE( state == RCV_WAIT_FOR_START_LOW); // state = WAIT_FOR_START_LOW run_data_collection = 0; data_collection_fsm(raw0, raw1, addr0, addr1, run_data_collection, cancel_data_collection, idle_data_collection, act_reg.mode, act_reg.energy_kev, act_reg.nframes, act_reg.nmodules, act_reg.nstorage_cells, act_reg.nsummation, state); REQUIRE(idle_data_collection == 0); REQUIRE(addr1.empty()); REQUIRE(raw1.empty()); REQUIRE( state == RCV_START); // state = START data_collection_fsm(raw0, raw1, addr0, addr1, run_data_collection, cancel_data_collection, idle_data_collection, act_reg.mode, act_reg.energy_kev, act_reg.nframes, act_reg.nmodules, act_reg.nstorage_cells, act_reg.nsummation, state); REQUIRE(idle_data_collection == 0); REQUIRE(raw1.size() == 1); REQUIRE( state == RCV_INIT); // state = INIT data_collection_fsm(raw0, raw1, addr0, addr1, run_data_collection, cancel_data_collection, idle_data_collection, act_reg.mode, act_reg.energy_kev, act_reg.nframes, act_reg.nmodules, act_reg.nstorage_cells, act_reg.nsummation, state); REQUIRE(idle_data_collection == 0); REQUIRE(raw1.size() == 1); REQUIRE( state == RCV_INIT); // state = INIT cancel_data_collection = 1; data_collection_fsm(raw0, raw1, addr0, addr1, run_data_collection, cancel_data_collection, idle_data_collection, act_reg.mode, act_reg.energy_kev, act_reg.nframes, act_reg.nmodules, act_reg.nstorage_cells, act_reg.nsummation, state); REQUIRE(idle_data_collection == 0); REQUIRE(raw1.size() == 1); // state = LAST REQUIRE( state == RCV_LAST); data_collection_fsm(raw0, raw1, addr0, addr1, run_data_collection, cancel_data_collection, idle_data_collection, act_reg.mode, act_reg.energy_kev, act_reg.nframes, act_reg.nmodules, act_reg.nstorage_cells, act_reg.nsummation, state); REQUIRE(idle_data_collection == 0); REQUIRE(addr1.size() == 1); REQUIRE(raw1.size() == 2); REQUIRE( state == RCV_WAIT_FOR_START); // state = WAIT_FOR_START data_collection_fsm(raw0, raw1, addr0, addr1, run_data_collection, cancel_data_collection, idle_data_collection, act_reg.mode, act_reg.energy_kev, act_reg.nframes, act_reg.nmodules, act_reg.nstorage_cells, act_reg.nsummation, state); REQUIRE( state == RCV_WAIT_FOR_START); REQUIRE(idle_data_collection == 1); REQUIRE(addr1.size() == 1); REQUIRE(raw1.size() == 2); auto packet = raw1.read(); REQUIRE(packet.last == 1); REQUIRE(packet.dest == 0); packet = raw1.read(); REQUIRE(packet.last); REQUIRE(packet.dest == 0); auto addr = addr1.read(); REQUIRE(addr.last); } TEST_CASE("HLS_C_Simulation_internal_packet_generator_15_storage_cell_convert_G0", "[FPGA][Full]") { const uint16_t nmodules = 2; const uint16_t ntrigger = 2; const uint16_t nstoragecells = 15; DiffractionExperiment x((DetectorGeometry(nmodules))); x.Mode(DetectorMode::Conversion); x.PedestalG0Frames(0).NumTriggers(ntrigger).ImagesPerTrigger(nstoragecells).UseInternalPacketGenerator(true) .PhotonEnergy_keV(10.0).StorageCells(nstoragecells); REQUIRE(x.GetImageNum() == ntrigger * nstoragecells); HLSSimulatedDevice test(0, ntrigger * nstoragecells * nmodules + 32); std::vector tmp(3 * RAW_MODULE_SIZE, 50); JFModuleGainCalibration gain(tmp); std::vector data(RAW_MODULE_SIZE); for (auto &i: data) i = 16000; for (int m = 0; m < x.GetModulesNum(); m++) test.SetInternalGeneratorFrame(data.data(), m); JFCalibration c(x); for (int i = 0; i < nstoragecells; i++) { for (int j = 0; j < RAW_MODULE_SIZE; j++) { c.Pedestal(0, 0, i).GetPedestal()[j] = (15 - i) * 500; c.Pedestal(1, 0, i).GetPedestal()[j] = i * 1000; } } c.GainCalibration(0) = gain; c.GainCalibration(1) = gain; REQUIRE_NOTHROW(test.InitializeCalibration(x, c)); REQUIRE_NOTHROW(test.StartAction(x)); REQUIRE_NOTHROW(test.WaitForActionComplete()); REQUIRE_NOTHROW(test.OutputStream().read()); REQUIRE(test.OutputStream().size() == 0); REQUIRE(test.GetBytesReceived() == ntrigger * nmodules * nstoragecells * 128 * JUNGFRAU_PACKET_SIZE_BYTES); for (int i = 0; i < ntrigger * nstoragecells; i++) { REQUIRE(test.GetDeviceOutput(i, 0)->pixels[511 * 764] == 32 - 15 + (i % nstoragecells)); REQUIRE(test.GetDeviceOutput(i, 1)->pixels[200 * 145] == 32 - 2 * (i % nstoragecells)); } } TEST_CASE("HLS_C_Simulation_internal_packet_generator_8_storage_cell_convert_G0", "[FPGA][Full]") { const uint16_t nmodules = 2; const uint16_t ntrigger = 2; const uint16_t nstoragecells = 8; DiffractionExperiment x((DetectorGeometry(nmodules))); x.Mode(DetectorMode::Conversion); x.PedestalG0Frames(0).NumTriggers(ntrigger).ImagesPerTrigger(nstoragecells).UseInternalPacketGenerator(true) .PhotonEnergy_keV(10.0).StorageCells(nstoragecells); REQUIRE(x.GetImageNum() == ntrigger * nstoragecells); HLSSimulatedDevice test(0, ntrigger * nstoragecells * nmodules + 64); std::vector tmp(3 * RAW_MODULE_SIZE, 50); JFModuleGainCalibration gain(tmp); std::vector data(RAW_MODULE_SIZE); for (auto &i: data) i = 16000; for (int m = 0; m < x.GetModulesNum(); m++) test.SetInternalGeneratorFrame(data.data(), m); JFCalibration c(x); for (int i = 0; i < nstoragecells; i++) { for (int j = 0; j < RAW_MODULE_SIZE; j++) { c.Pedestal(0, 0, i).GetPedestal()[j] = (15 - i) * 500; c.Pedestal(1, 0, i).GetPedestal()[j] = i * 1000; } } c.GainCalibration(0) = gain; c.GainCalibration(1) = gain; REQUIRE_NOTHROW(test.InitializeCalibration(x, c)); REQUIRE_NOTHROW(test.StartAction(x)); REQUIRE_NOTHROW(test.WaitForActionComplete()); REQUIRE_NOTHROW(test.OutputStream().read()); REQUIRE(test.OutputStream().size() == 0); REQUIRE(test.GetBytesReceived() == ntrigger * nmodules * nstoragecells * 128 * JUNGFRAU_PACKET_SIZE_BYTES); for (int i = 0; i < ntrigger * nstoragecells; i++) { REQUIRE(test.GetDeviceOutput(i, 0)->pixels[511 * 764] == 32 - 15 + (i % nstoragecells)); REQUIRE(test.GetDeviceOutput(i, 1)->pixels[200 * 145] == 32 - 2 * (i % nstoragecells)); } } TEST_CASE("HLS_C_Simulation_internal_packet_generator_16_storage_cell_convert_G0", "[FPGA][Full]") { const uint16_t nmodules = 2; const uint16_t ntrigger = 4; const uint16_t nstoragecells = 16; DiffractionExperiment x((DetectorGeometry(nmodules))); x.Mode(DetectorMode::Conversion); x.PedestalG0Frames(0).NumTriggers(ntrigger).ImagesPerTrigger(nstoragecells).UseInternalPacketGenerator(true) .PhotonEnergy_keV(10.0).StorageCells(nstoragecells); REQUIRE(x.GetImageNum() == ntrigger * nstoragecells); HLSSimulatedDevice test(0, ntrigger * nstoragecells * nmodules + 128); std::vector tmp(3 * RAW_MODULE_SIZE, 50); JFModuleGainCalibration gain(tmp); std::vector data(RAW_MODULE_SIZE); for (auto &i: data) i = 16000; for (int m = 0; m < x.GetModulesNum(); m++) test.SetInternalGeneratorFrame(data.data(), m); JFCalibration c(x); for (int i = 0; i < nstoragecells; i++) { for (int j = 0; j < RAW_MODULE_SIZE; j++) { c.Pedestal(0, 0, i).GetPedestal()[j] = (15 - i) * 500; c.Pedestal(1, 0, i).GetPedestal()[j] = i * 1000; } } c.GainCalibration(0) = gain; c.GainCalibration(1) = gain; REQUIRE_NOTHROW(test.InitializeCalibration(x, c)); REQUIRE_NOTHROW(test.StartAction(x)); REQUIRE_NOTHROW(test.WaitForActionComplete()); REQUIRE_NOTHROW(test.OutputStream().read()); REQUIRE(test.OutputStream().size() == 0); REQUIRE(test.GetBytesReceived() == ntrigger * nmodules * nstoragecells * 128 * JUNGFRAU_PACKET_SIZE_BYTES); for (int i = 0; i < ntrigger * nstoragecells; i++) { REQUIRE(test.GetDeviceOutput(i, 0)->pixels[511 * 764] == 32 - 15 + (i % nstoragecells)); REQUIRE(test.GetDeviceOutput(i, 1)->pixels[200 * 145] == 32 - 2 * (i % nstoragecells)); } } TEST_CASE("HLS_C_Simulation_internal_packet_generator_storage_cell_convert_G1", "[FPGA][Full]") { const uint16_t nmodules = 2; DiffractionExperiment x((DetectorGeometry(nmodules))); x.Mode(DetectorMode::Conversion); x.PedestalG0Frames(0).NumTriggers(1).ImagesPerTrigger(16).UseInternalPacketGenerator(true) .PhotonEnergy_keV(10.0).StorageCells(16); HLSSimulatedDevice test(0, 64); std::vector data(RAW_MODULE_SIZE); for (auto &i: data) i = 16384 | 10; for (int m = 0; m < x.GetModulesNum(); m++) test.SetInternalGeneratorFrame(data.data(), m); JFCalibration c(x); for (int i = 0; i < 16; i++) { for (int j = 0; j < RAW_MODULE_SIZE; j++) { c.Pedestal(0, 1, i).GetPedestal()[j] = (17 - i) * 10; c.Pedestal(1, 1, i).GetPedestal()[j] = i * 20; } } std::vector tmp(3 * RAW_MODULE_SIZE, -1); for (int i = 0; i < RAW_MODULE_SIZE; i++) tmp[i] = DEFAULT_G0_FACTOR; JFModuleGainCalibration gain(tmp); c.GainCalibration(0) = gain; c.GainCalibration(1) = gain; REQUIRE_NOTHROW(test.InitializeCalibration(x, c)); REQUIRE_NOTHROW(test.StartAction(x)); REQUIRE_NOTHROW(test.WaitForActionComplete()); REQUIRE_NOTHROW(test.OutputStream().read()); REQUIRE(test.OutputStream().size() == 0); REQUIRE(test.GetBytesReceived() == 32*128*JUNGFRAU_PACKET_SIZE_BYTES); for (int i = 0; i < 16; i++) { REQUIRE(test.GetDeviceOutput(i, 0)->pixels[511 * 764] == 17 - (i % 16) - 1); REQUIRE(test.GetDeviceOutput(i, 1)->pixels[200 * 145] == 2 * (i % 16) - 1); } } 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); for (int i = 0; i < RAW_MODULE_SIZE; i++) frame[i] = 32754; for (int m = 0; m < x.GetModulesNum(); m++) test.SetInternalGeneratorFrame(frame.data(), m); 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; } std::vector weights(nmodules * RAW_MODULE_SIZE, 1.0); integration_map[RAW_MODULE_SIZE - 1] = FPGA_INTEGRATION_BIN_COUNT; test.InitializeIntegrationMap(x, integration_map, weights); REQUIRE_NOTHROW(test.StartAction(x)); REQUIRE_NOTHROW(test.WaitForActionComplete()); REQUIRE(test.OutputStream().size() == 1); REQUIRE(test.GetBytesReceived() == 128 * nmodules * JUNGFRAU_PACKET_SIZE_BYTES); auto imageBuf = test.GetDeviceOutput(0, 0)->pixels; REQUIRE(memcmp(imageBuf, frame.data(), RAW_MODULE_SIZE * sizeof(uint16_t)) == 0); auto integration_result = test.GetDeviceOutput(0, 0)->integration_result; CHECK(integration_result[0].sum == Approx(32754LU * (RAW_MODULE_SIZE / 2))); CHECK(integration_result[0].count == RAW_MODULE_SIZE / 2); CHECK(integration_result[1].sum == 0); CHECK(integration_result[1].count == 0); CHECK(integration_result[FPGA_INTEGRATION_BIN_COUNT - 1].sum == Approx(32754LU * (RAW_MODULE_SIZE / 2 - 1))); CHECK(integration_result[FPGA_INTEGRATION_BIN_COUNT - 1].count == RAW_MODULE_SIZE / 2 - 1); integration_result = test.GetDeviceOutput(0, 1)->integration_result; CHECK(integration_result[54].sum == Approx(32754LU * (RAW_MODULE_SIZE))); CHECK(integration_result[54].count == RAW_MODULE_SIZE); integration_result = test.GetDeviceOutput(0, 2)->integration_result; CHECK(integration_result[54].sum == Approx(32754 * (RAW_MODULE_SIZE))); CHECK(integration_result[54].count == RAW_MODULE_SIZE); integration_result = test.GetDeviceOutput(0, 3)->integration_result; CHECK(integration_result[54].sum == Approx(32754 * (RAW_MODULE_SIZE))); CHECK(integration_result[54].count == RAW_MODULE_SIZE); } bool spot_finder_output_contains(const SpotFindingResult& output, uint32_t number) { size_t byte = number / 8; size_t bit = number % 8; return ((output.strong_pixel[byte] & (1 << bit)) != 0); } TEST_CASE("HLS_C_Simulation_internal_packet_generator_spot_finder_count_threshold", "[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, 0); frame [ 0] = 11; frame [123*1024 + 578] = 10; frame [121*1024 + 800] = 12; frame [ 89*1024 + 300] = 8; frame [300*1024 + 0] = 9; for (int m = 0; m < x.GetModulesNum(); m++) test.SetInternalGeneratorFrame(frame.data(), m); SpotFindingSettings parameters{ .signal_to_noise_threshold = 0.0, .photon_count_threshold = 9, .min_pix_per_spot = 1 }; test.SetSpotFinderParameters(parameters); REQUIRE_NOTHROW(test.StartAction(x)); REQUIRE_NOTHROW(test.WaitForActionComplete()); REQUIRE(test.OutputStream().size() == 1); REQUIRE(test.GetBytesReceived() == 128 * nmodules * JUNGFRAU_PACKET_SIZE_BYTES); auto imageBuf = test.GetDeviceOutput(0, 0)->pixels; REQUIRE(memcmp(imageBuf, frame.data(), RAW_MODULE_SIZE * sizeof(uint16_t)) == 0); auto spot_finder_result = test.GetDeviceOutput(0, 0)->spot_finding_result; REQUIRE (spot_finder_result.strong_pixel_count == 3); REQUIRE (spot_finder_result.snr_threshold == 0); REQUIRE (spot_finder_result.count_threshold == 9); CHECK (spot_finder_output_contains(spot_finder_result, 0)); CHECK (spot_finder_output_contains(spot_finder_result, 123*1024 + 578)); CHECK (spot_finder_output_contains(spot_finder_result, 121*1024 + 800)); } TEST_CASE("HLS_C_Simulation_internal_packet_generator_spot_finder_min_pix_per_spot", "[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, 0); frame [ 0] = 11; frame [ 1] = 10; frame [ 1024] = 12; frame [2*1024] = 12; frame [ 89*1024+154] = 12; frame [ 99*1024+200] = 12; frame [100*1024+200] = 11; frame [100*1024+201] = 10; frame [101*1024+200] = 12; frame [RAW_MODULE_SIZE - 1] = 20; for (int m = 0; m < x.GetModulesNum(); m++) test.SetInternalGeneratorFrame(frame.data(), m); SpotFindingSettings parameters{ .signal_to_noise_threshold = 0.0, .photon_count_threshold = 9, .min_pix_per_spot = 2 }; test.SetSpotFinderParameters(parameters); REQUIRE_NOTHROW(test.StartAction(x)); REQUIRE_NOTHROW(test.WaitForActionComplete()); REQUIRE(test.OutputStream().size() == 1); REQUIRE(test.GetBytesReceived() == 128 * nmodules * JUNGFRAU_PACKET_SIZE_BYTES); auto imageBuf = test.GetDeviceOutput(0, 0)->pixels; REQUIRE(memcmp(imageBuf, frame.data(), RAW_MODULE_SIZE * sizeof(uint16_t)) == 0); auto spot_finder_result = test.GetDeviceOutput(0, 0)->spot_finding_result; REQUIRE (spot_finder_result.strong_pixel_count == 8); REQUIRE (spot_finder_result.snr_threshold == 0); REQUIRE (spot_finder_result.count_threshold == 9); CHECK (spot_finder_output_contains(spot_finder_result, 0)); CHECK (spot_finder_output_contains(spot_finder_result, 1)); CHECK (spot_finder_output_contains(spot_finder_result, 1024)); CHECK (!spot_finder_output_contains(spot_finder_result, RAW_MODULE_SIZE-1)); CHECK (!spot_finder_output_contains(spot_finder_result, 89*1024+154)); } TEST_CASE("HLS_C_Simulation_internal_packet_generator_spot_finder_d_min_max", "[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 d_map(RAW_MODULE_SIZE, 0.0); d_map[0] = 2.5; d_map[1] = 4.0; d_map[2] = 1.0; d_map[3] = 1.5; std::vector frame(RAW_MODULE_SIZE, 0); frame [ 0] = 11; frame [ 1] = 10; frame [ 2] = 12; frame [ 3] = 12; test.InitializeSpotFinderResolutionMap(d_map.data(), 0); for (int m = 0; m < x.GetModulesNum(); m++) test.SetInternalGeneratorFrame(frame.data(), m); SpotFindingSettings parameters{ .signal_to_noise_threshold = 0.0, .photon_count_threshold = 9, .min_pix_per_spot = 1, .high_resolution_limit = 1.25, .low_resolution_limit = 3.0 }; test.SetSpotFinderParameters(parameters); REQUIRE_NOTHROW(test.StartAction(x)); REQUIRE_NOTHROW(test.WaitForActionComplete()); REQUIRE(test.OutputStream().size() == 1); REQUIRE(test.GetBytesReceived() == 128 * nmodules * JUNGFRAU_PACKET_SIZE_BYTES); auto imageBuf = test.GetDeviceOutput(0, 0)->pixels; REQUIRE(memcmp(imageBuf, frame.data(), RAW_MODULE_SIZE * sizeof(uint16_t)) == 0); auto spot_finder_result = test.GetDeviceOutput(0, 0)->spot_finding_result; REQUIRE (spot_finder_result.strong_pixel_count == 2); REQUIRE (spot_finder_result.snr_threshold == 0); REQUIRE (spot_finder_result.count_threshold == 9); CHECK (spot_finder_output_contains(spot_finder_result, 0)); CHECK (spot_finder_output_contains(spot_finder_result, 3)); } TEST_CASE("HLS_C_Simulation_internal_packet_generator_spot_finder_snr_threshold", "[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); for (int i = 0; i < RAW_MODULE_SIZE; i++) { frame[i] = ((i / RAW_MODULE_COLS) + (i % RAW_MODULE_COLS)) % 2; } // Mean = 0.5 // Std. dev. = 0.5 // Threshold = 10 * std. dev. - 6 is minimum count frame [ 0] = 8; frame [123*1024 + 578] = 5; frame [121*1024 + 800] = 4; frame [ 89*1024 + 300] = 7; frame [300*1024 + 0] = 3; for (int m = 0; m < x.GetModulesNum(); m++) test.SetInternalGeneratorFrame(frame.data(), m); SpotFindingSettings parameters{ .signal_to_noise_threshold = 10.0, .photon_count_threshold = 0, .min_pix_per_spot = 1 }; test.SetSpotFinderParameters(parameters); REQUIRE_NOTHROW(test.StartAction(x)); REQUIRE_NOTHROW(test.WaitForActionComplete()); REQUIRE(test.OutputStream().size() == 1); REQUIRE(test.GetBytesReceived() == 128 * nmodules * JUNGFRAU_PACKET_SIZE_BYTES); auto imageBuf = test.GetDeviceOutput(0, 0)->pixels; REQUIRE(memcmp(imageBuf, frame.data(), RAW_MODULE_SIZE * sizeof(uint16_t)) == 0); auto spot_finder_result = test.GetDeviceOutput(0, 0)->spot_finding_result; REQUIRE (spot_finder_result.strong_pixel_count == 2); REQUIRE (spot_finder_result.snr_threshold == 10.0); REQUIRE (spot_finder_result.count_threshold == 0); REQUIRE (spot_finder_output_contains(spot_finder_result, 0)); REQUIRE (spot_finder_output_contains(spot_finder_result, 89*1024 + 300)); } TEST_CASE("HLS_C_Simulation_internal_packet_generator_32bit", "[FPGA][Full]") { const uint16_t nmodules = 1; const size_t nframes = 2; DiffractionExperiment x((DetectorGeometry(nmodules))); std::vector test_frame(nmodules*RAW_MODULE_SIZE); std::mt19937 g1(1387); std::uniform_int_distribution dist(0, UINT16_MAX - 1); for (auto &i: test_frame) i = dist(g1); x.Mode(DetectorMode::Raw); x.UseInternalPacketGenerator(true).ImagesPerTrigger(nframes).PedestalG0Frames(0).FPGAOutputMode(FPGAPixelOutput::Uint32); HLSSimulatedDevice test(0, 64); for (int m = 0; m < x.GetModulesNum(); m++) test.SetInternalGeneratorFrame(test_frame.data() + m * RAW_MODULE_SIZE, m); REQUIRE_NOTHROW(test.StartAction(x)); REQUIRE_NOTHROW(test.WaitForActionComplete()); REQUIRE(test.OutputStream().size() == 1); REQUIRE(test.GetBytesReceived() == 128 * nmodules * nframes * JUNGFRAU_PACKET_SIZE_BYTES); auto test_frame_unsigned = (uint16_t *) test_frame.data(); for (int image = 0; image < nframes; image++) { for (int m = 0; m < nmodules; m++) { CHECK(test.GetDeviceOutput(image, m)->module_statistics.frame_number == image); CHECK(test.GetDeviceOutput(image, m)->module_statistics.packet_count == 256); CHECK(test.GetDeviceOutput(image, m)->module_statistics.packet_mask[0] == UINT64_MAX); CHECK(test.GetDeviceOutput(image, m)->module_statistics.packet_mask[1] == UINT64_MAX); CHECK(test.GetDeviceOutput(image, m)->module_statistics.packet_mask[2] == UINT64_MAX); CHECK(test.GetDeviceOutput(image, m)->module_statistics.packet_mask[3] == UINT64_MAX); CHECK(test.GetDeviceOutput(image, m)->module_statistics.timestamp == INT_PKT_GEN_EXPTTIME * image); CHECK(test.GetDeviceOutput(image, m)->module_statistics.pulse_id == INT_PKT_GEN_BUNCHID + image); CHECK(test.GetDeviceOutput(image, m)->module_statistics.exptime == INT_PKT_GEN_EXPTTIME); auto imageBuf = (uint32_t *) test.GetDeviceOutput(image, m)->pixels; for (int i = 0; i < RAW_MODULE_SIZE; i++) { REQUIRE(imageBuf[i] == test_frame_unsigned[m * RAW_MODULE_SIZE + i]); } } } } TEST_CASE("HLS_C_Simulation_internal_packet_generator_summation", "[FPGA][Full]") { const uint16_t nmodules = 1; const size_t nframes = 16; const size_t nsummation = 16; DiffractionExperiment x((DetectorGeometry(nmodules))); std::vector test_frame(nmodules*RAW_MODULE_SIZE); std::mt19937 g1(1387); std::uniform_int_distribution dist(0, UINT16_MAX); for (auto &i: test_frame) i = dist(g1); x.Mode(DetectorMode::Conversion); x.UseInternalPacketGenerator(true).ImagesPerTrigger(nframes).PedestalG0Frames(0).Summation(nsummation) .ConversionOnFPGA(false).FPGAOutputMode(FPGAPixelOutput::Int32); HLSSimulatedDevice test(0, 64); for (int m = 0; m < x.GetModulesNum(); m++) test.SetInternalGeneratorFrame(test_frame.data() + m * RAW_MODULE_SIZE, m); REQUIRE_NOTHROW(test.StartAction(x)); REQUIRE_NOTHROW(test.WaitForActionComplete()); REQUIRE(test.OutputStream().size() == 1); REQUIRE(test.GetBytesReceived() == 128 * nmodules * nframes * nsummation * JUNGFRAU_PACKET_SIZE_BYTES); auto test_frame_signed = (int16_t *) test_frame.data(); for (int image = 0; image < nframes; image++) { for (int m = 0; m < nmodules; m++) { REQUIRE(test.GetDeviceOutput(image, m)->module_statistics.timestamp == INT_PKT_GEN_EXPTTIME * image * nsummation); REQUIRE(test.GetDeviceOutput(image, m)->module_statistics.pulse_id == INT_PKT_GEN_BUNCHID + image * nsummation); REQUIRE(test.GetDeviceOutput(image, m)->module_statistics.exptime == INT_PKT_GEN_EXPTTIME); auto imageBuf = (int32_t *) test.GetDeviceOutput(image, m)->pixels; for (int i = 0; i < RAW_MODULE_SIZE; i++) { if (test_frame_signed[m * RAW_MODULE_SIZE + i] == INT16_MAX) CHECK(imageBuf[i] == INT32_MAX); else if (test_frame_signed[m * RAW_MODULE_SIZE + i] == INT16_MIN) CHECK(imageBuf[i] == INT32_MIN); else REQUIRE(imageBuf[i] == test_frame_signed[m * RAW_MODULE_SIZE + i] * nsummation); } } } } #define NFRAMES_PEDESTAL_CHECK 256 TEST_CASE("HLS_C_Simulation_check_convert_pedestal", "[FPGA][Full]") { DiffractionExperiment x(DetectorGeometry(4)); HLSSimulatedDevice test(0, NFRAMES_PEDESTAL_CHECK*4+8); for (int gain = 2; gain >= 0; gain--) { x.ImagesPerTrigger(1).PedestalG0Frames(500).PedestalG1Frames(500).PedestalG2Frames(500).NumTriggers(1); std::vector data(NFRAMES_PEDESTAL_CHECK * RAW_MODULE_SIZE); double mean; double stddev; if (gain == 0) { x.Mode(DetectorMode::PedestalG0); mean = 1000.0; stddev = 50.0; } else if (gain == 1) { x.Mode(DetectorMode::PedestalG1); mean = 13000.0; stddev = 40.0; } else { // gain == 2 x.Mode(DetectorMode::PedestalG2); mean = 14500.0; stddev = 20.0; } // Predictable random number generator std::mt19937 g1(1984+gain); std::normal_distribution distribution(mean, stddev); for (int i = 0; i < NFRAMES_PEDESTAL_CHECK; i++) { for (int j = 0; j < RAW_MODULE_SIZE; j++) { double number = distribution(g1); if (number < 20) number = 20; if (number > 16300) number = 16300; data[i * RAW_MODULE_SIZE + j] = number + ((gain == 1)?0x4000:0) + ((gain == 2)? 0xc000:0); } } data[0 + 4096 * 45] = 0x4000 + 1; // gain_bit always 1 data[1 + 4096 * 3] = 0x8000 + 1; // gain_bit always 2 data[2 + 4096 * 100] = 0xc000 + 1; // gain_bit always 3 test.CreateJFPackets(x, 1, NFRAMES_PEDESTAL_CHECK, 0, data.data()); test.CreateFinalPacket(x); REQUIRE_NOTHROW(test.StartAction(x)); REQUIRE_NOTHROW(test.WaitForActionComplete()); REQUIRE_NOTHROW(test.OutputStream().read()); REQUIRE(test.OutputStream().size() == 0); REQUIRE(test.GetBytesReceived() == NFRAMES_PEDESTAL_CHECK * 128 * JUNGFRAU_PACKET_SIZE_BYTES); REQUIRE(test.Counters().GetPedestalBufferHandle(0, 1) == AcquisitionCounters::HandleNotFound); REQUIRE(test.Counters().GetPedestalBufferHandle(0, 0) != AcquisitionCounters::HandleNotFound); auto pedestal_buffer_0 = test.GetDeviceOutputPedestal(0, 0); REQUIRE(pedestal_buffer_0->module_statistics.packet_count == NFRAMES_PEDESTAL_CHECK); JFPedestalCalc reference(x); for (int i = 0; i < NFRAMES_PEDESTAL_CHECK; i++) reference.AnalyzeImage(data.data() + i * RAW_MODULE_SIZE); JFModulePedestal reference_pedestal, fpga_pedestal; reference.Export(reference_pedestal); fpga_pedestal.ImportFPGAPedestal(pedestal_buffer_0); float error = 0; for (int i = 0; i < RAW_MODULE_SIZE; i++) { float diff = reference_pedestal.GetPedestal()[i] - fpga_pedestal.GetPedestal()[i]; error += diff * diff; } error = sqrtf(error / RAW_MODULE_SIZE); std::cout << "Pedestal G" << gain << " error: " << error << std::endl; REQUIRE(error < 0.5); } } TEST_CASE("HLS_C_Simulation_count_sat_and_err_pixels", "[FPGA][Full]") { const uint16_t nmodules = 3; DiffractionExperiment x((DetectorGeometry(nmodules))); x.Mode(DetectorMode::Raw); x.UseInternalPacketGenerator(true).ImagesPerTrigger(4).PedestalG0Frames(0); HLSSimulatedDevice test(0, 64); std::vector v(RAW_MODULE_SIZE, 0); v[567] = 0xc000; v[RAW_MODULE_COLS * 511 + 255] = 0xc000; v[RAW_MODULE_COLS * 250 + 233] = 0xffff; v[0] = 0xffff; v[RAW_MODULE_SIZE-1] = 0xffff; for (int m = 0; m < x.GetModulesNum(); m++) test.SetInternalGeneratorFrame(v.data(), m); REQUIRE_NOTHROW(test.StartAction(x)); REQUIRE_NOTHROW(test.WaitForActionComplete()); REQUIRE(test.OutputStream().size() == 1); REQUIRE(test.GetBytesReceived() == 128 * nmodules * 4 * JUNGFRAU_PACKET_SIZE_BYTES); for (int image = 0; image < 4; image++) { for (int m = 0; m < nmodules; m++) { CHECK(test.GetDeviceOutput(image, m)->module_statistics.saturated_pixels == 2); CHECK(test.GetDeviceOutput(image, m)->module_statistics.err_pixels == 3); } } } TEST_CASE("HLS_C_Simulation_check_bunchid", "[FPGA][Full]") { const uint64_t bunchid = 0xAAAAAAAA87345600; const uint16_t nmodules = 4; DiffractionExperiment x((DetectorGeometry(nmodules))); x.Mode(DetectorMode::Raw); x.PedestalG0Frames(0).ImagesPerTrigger(3).NumTriggers(1); HLSSimulatedDevice test(0, 64); test.CreateXfelBunchIDPacket(bunchid, 0); test.CreateFinalPacket(x); REQUIRE_NOTHROW(test.StartAction(x)); REQUIRE_NOTHROW(test.WaitForActionComplete()); REQUIRE_NOTHROW(test.OutputStream().read()); REQUIRE(test.OutputStream().size() == 0); REQUIRE(test.GetBytesReceived() == 0); REQUIRE(test.GetDataCollectionStatus().current_pulseid == bunchid); } TEST_CASE("HLS_C_Simulation_check_raw_eiger", "[FPGA][Full]") { std::vector raw_frame(RAW_MODULE_SIZE); std::vector raw_frame_eiger(RAW_MODULE_SIZE); for (int i = 0; i < RAW_MODULE_SIZE; i++) raw_frame[i] = i % (UINT16_MAX - 11); RawToEigerInput(raw_frame_eiger.data(), raw_frame.data()); const uint16_t nmodules = 1; DiffractionExperiment x((DetectorGeometry(nmodules))); x.Mode(DetectorMode::Raw); x.PedestalG0Frames(0).ImagesPerTrigger(1).NumTriggers(1); HLSSimulatedDevice test(0, 64); // bottom half module is reversed for (int i = 0; i < 64; i++) test.CreateEIGERPacket(x, 1, i, 0, 0, 0, raw_frame_eiger.data() + 2048 * (2 * i)); for (int i = 0; i < 64; i++) test.CreateEIGERPacket(x, 1, i, 0, 1, 0, raw_frame_eiger.data() + 2048 * (1 + 2 * i)); for (int i = 0; i < 64; i++) test.CreateEIGERPacket(x, 1, i, 0, 0, 1, raw_frame_eiger.data() + 2048 * (128 + 2 * i)); for (int i = 0; i < 64; i++) test.CreateEIGERPacket(x, 1, i, 0, 1, 1, raw_frame_eiger.data() + 2048 * (129 + 2 * i)); test.CreateFinalPacket(x); REQUIRE_NOTHROW(test.StartAction(x)); REQUIRE_NOTHROW(test.WaitForActionComplete()); REQUIRE(test.Counters().GetSlowestFrameNumber() == 0); REQUIRE_NOTHROW(test.OutputStream().read()); REQUIRE(test.OutputStream().size() == 0); REQUIRE(test.GetBytesReceived() == 256 * 4096); uint64_t diffs = 0; for (int j = 0; j < RAW_MODULE_SIZE; j++) { if (raw_frame[j] != ((uint16_t *) test.GetDeviceOutput(0, 0)->pixels)[j]) diffs++; } REQUIRE(diffs == 0); } TEST_CASE("HLS_C_Simulation_internal_packet_generator_eiger", "[FPGA][Full]") { std::vector raw_frame(RAW_MODULE_SIZE), raw_frame_eiger(RAW_MODULE_SIZE); std::mt19937 g1(1387); std::uniform_int_distribution dist(0, 65535); for (int i = 0; i < RAW_MODULE_SIZE; i++) raw_frame[i] = dist(g1); RawToEigerInput(raw_frame_eiger.data(), raw_frame.data()); const uint16_t nmodules = 4; DiffractionExperiment x(DetectorSetup(DetectorGeometry(nmodules), DetectorType::EIGER)); x.Mode(DetectorMode::Raw); x.UseInternalPacketGenerator(true).ImagesPerTrigger(4).PedestalG0Frames(0); HLSSimulatedDevice test(0, 64); for (int m = 0; m < x.GetModulesNum(); m++) test.SetInternalGeneratorFrame(raw_frame_eiger.data(), m); REQUIRE_NOTHROW(test.StartAction(x)); REQUIRE_NOTHROW(test.WaitForActionComplete()); REQUIRE(test.OutputStream().size() == 1); REQUIRE(test.GetBytesReceived() == 128 * nmodules * 4 * JUNGFRAU_PACKET_SIZE_BYTES); for (int image = 0; image < 4; image++) { for (int m = 0; m < nmodules; m++) { auto imageBuf = (uint16_t *) test.GetDeviceOutput(image, m)->pixels; for (int i = 0; i < RAW_MODULE_SIZE; i++) REQUIRE(imageBuf[i] == raw_frame[i]); } } REQUIRE(test.GetExpectedDescriptorsPerModule() == DMA_DESCRIPTORS_PER_MODULE); } TEST_CASE("HLS_C_Simulation_internal_packet_generator_roi_calc", "[FPGA][Full]") { const uint16_t nmodules = 4; const size_t nimages = 4; DiffractionExperiment x((DetectorGeometry(nmodules))); x.Mode(DetectorMode::Raw); x.UseInternalPacketGenerator(true).ImagesPerTrigger(nimages).PedestalG0Frames(0); HLSSimulatedDevice test(0, 64); std::vector frame(RAW_MODULE_SIZE); for (int i = 0; i < RAW_MODULE_SIZE; i++) frame[i] = 135; frame[12+RAW_MODULE_COLS*3] = 83; frame[13+RAW_MODULE_COLS*3] = 95; frame[12+RAW_MODULE_COLS*4] = 13; frame[13+RAW_MODULE_COLS*4] = 125; frame[812+RAW_MODULE_COLS*303] = 83; frame[813+RAW_MODULE_COLS*303] = 95; frame[812+RAW_MODULE_COLS*304] = 13; frame[813+RAW_MODULE_COLS*304] = 125; std::vector roi_map(RAW_MODULE_SIZE, UINT16_MAX); roi_map[12+RAW_MODULE_COLS*3] = 0; roi_map[13+RAW_MODULE_COLS*3] = 0; roi_map[12+RAW_MODULE_COLS*4] = 0; roi_map[13+RAW_MODULE_COLS*4] = 0; roi_map[812+RAW_MODULE_COLS*303] = 1; roi_map[813+RAW_MODULE_COLS*303] = 1; roi_map[812+RAW_MODULE_COLS*304] = 1; roi_map[813+RAW_MODULE_COLS*304] = 1; for (int m = 0; m < x.GetModulesNum(); m++) { test.SetInternalGeneratorFrame(frame.data(), m); test.InitializeROIMap(roi_map.data(), m); } REQUIRE_NOTHROW(test.StartAction(x)); REQUIRE_NOTHROW(test.WaitForActionComplete()); REQUIRE(test.OutputStream().size() == 1); REQUIRE(test.GetBytesReceived() == 128 * nimages * nmodules * JUNGFRAU_PACKET_SIZE_BYTES); auto imageBuf = test.GetDeviceOutput(0, 0)->pixels; REQUIRE(memcmp(imageBuf, frame.data(), RAW_MODULE_SIZE * sizeof(uint16_t)) == 0); for (int i = 0; i < x.GetImageNum(); i++) { for (int m = 0; m < x.GetModulesNum(); m++) { CHECK (test.GetDeviceOutput(i, m)->roi_counts[0].sum == 83 + 95 + 13 + 125); CHECK (test.GetDeviceOutput(i, m)->roi_counts[0].sum2 == 83 * 83 + 95 * 95 + 13 * 13 + 125 * 125); CHECK (test.GetDeviceOutput(i, m)->roi_counts[0].sum_x_weighted == Approx(83 * 12 + 95 * 13 + 13 * 12 + 125 * 13)); CHECK (test.GetDeviceOutput(i, m)->roi_counts[0].sum_y_weighted == Approx(83 * 3 + 95 * 3 + 13 * 4 + 125 * 4)); CHECK (test.GetDeviceOutput(i, m)->roi_counts[0].max_value == 125); CHECK (test.GetDeviceOutput(i, m)->roi_counts[0].good_pixels == 4); CHECK (test.GetDeviceOutput(i, m)->roi_counts[1].sum_x_weighted == Approx(83 * (812+6) + 95 * (813+6) + 13 * (812+6) + 125 * (813+6))); CHECK (test.GetDeviceOutput(i, m)->roi_counts[1].sum_y_weighted == Approx(83 * (303+2) + 95 * (303+2) + 13 * (304+2) + 125 * (304+2))); } } } TEST_CASE("HLS_C_Simulation_internal_packet_generator_4_images", "[FPGA][Full]") { const uint16_t nmodules = 4; const uint16_t nimages = 4; DiffractionExperiment x((DetectorGeometry(nmodules))); x.Mode(DetectorMode::Raw); x.UseInternalPacketGenerator(true).ImagesPerTrigger(nimages).PedestalG0Frames(0).InternalPacketGeneratorImages(nimages); HLSSimulatedDevice test(0, 64); std::vector ref_data(RAW_MODULE_SIZE*nimages*nmodules); for (int i = 0; i < ref_data.size(); i++) ref_data[i] = (7 * i + 5) % 65521; for (int m = 0; m < nmodules*nimages; m++) test.SetInternalGeneratorFrame(ref_data.data() + RAW_MODULE_SIZE * m, m); REQUIRE_NOTHROW(test.StartAction(x)); REQUIRE_NOTHROW(test.WaitForActionComplete()); REQUIRE(test.OutputStream().size() == 1); REQUIRE(test.GetBytesReceived() == 128 * nmodules * 4 * JUNGFRAU_PACKET_SIZE_BYTES); for (int image = 0; image < 4; image++) { for (int m = 0; m < nmodules; m++) { std::cout << image << " " << m << std::endl; auto imageBuf = (uint16_t *) test.GetDeviceOutput(image, m)->pixels; for (int i = 0; i < RAW_MODULE_SIZE; i++) REQUIRE(imageBuf[i] == ref_data[i + (image * nmodules + m) * RAW_MODULE_SIZE]); } } }