Extend FPGA functionality

This commit is contained in:
2023-12-09 12:08:39 +01:00
parent 35a9614f38
commit 1798de247b
97 changed files with 2302 additions and 3672 deletions
+116 -21
View File
@@ -3,7 +3,6 @@
#include <catch2/catch.hpp>
#include <random>
#include <bitshuffle/bitshuffle.h>
#include "../jungfrau/JFPedestalCalc.h"
#include "../acquisition_device/HLSSimulatedDevice.h"
#include "FPGAUnitTest.h"
@@ -35,7 +34,8 @@ TEST_CASE("HLS_C_Simulation_internal_packet_generator", "[FPGA][Full]") {
REQUIRE(imageBuf[i] == i % 65536);
}
}
REQUIRE(test.GetCompletedDescriptors() == 2 * (4 + DELAY_FRAMES_STOP_AND_QUIT - 1) * nmodules);
REQUIRE(test.GetExpectedDescriptorsPerModule() == 5);
REQUIRE(test.GetCompletedDescriptors() == 5 * (4 + DELAY_FRAMES_STOP_AND_QUIT - 1) * nmodules);
}
TEST_CASE("HLS_C_Simulation_internal_packet_generator_custom_frame", "[FPGA][Full]") {
@@ -66,9 +66,9 @@ TEST_CASE("HLS_C_Simulation_internal_packet_generator_custom_frame", "[FPGA][Ful
for (int image = 0; image < nframes; image++) {
for (int m = 0; m < nmodules; m++) {
REQUIRE(test.Counters().GetCompletion(image, m).timestamp == INT_PKT_GEN_EXPTTIME * image);
REQUIRE(test.Counters().GetCompletion(image, m).bunchid == INT_PKT_GEN_BUNCHID + image);
REQUIRE(test.Counters().GetCompletion(image, m).exptime == INT_PKT_GEN_EXPTTIME);
REQUIRE(test.GetDeviceOutput(image, m)->module_statistics.timestamp == INT_PKT_GEN_EXPTTIME * image);
REQUIRE(test.GetDeviceOutput(image, m)->module_statistics.bunchid == INT_PKT_GEN_BUNCHID + image);
REQUIRE(test.GetDeviceOutput(image, m)->module_statistics.exptime == INT_PKT_GEN_EXPTTIME);
auto imageBuf = (uint16_t *) test.GetDeviceOutput(image, m)->pixels;
for (int i = 0; i < RAW_MODULE_SIZE; i++) {
@@ -340,6 +340,7 @@ TEST_CASE("HLS_C_Simulation_check_single_packet", "[FPGA][Full]") {
}
TEST_CASE("HLS_C_Simulation_check_convert_full_range", "[FPGA][Full]") {
Logger logger("HLS_C_Simulation_check_convert_full_range");
std::vector<uint16_t> data(RAW_MODULE_SIZE);
std::vector<double> gain(3 * RAW_MODULE_SIZE);
@@ -359,8 +360,8 @@ TEST_CASE("HLS_C_Simulation_check_convert_full_range", "[FPGA][Full]") {
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);
REQUIRE(x.GetPhotonEnergy_keV() == Approx(energy));
@@ -381,7 +382,7 @@ TEST_CASE("HLS_C_Simulation_check_convert_full_range", "[FPGA][Full]") {
REQUIRE_NOTHROW(test.OutputStream().read());
REQUIRE(test.OutputStream().size() == 0);
REQUIRE(test.GetBytesReceived() == 128 * JUNGFRAU_PACKET_SIZE_BYTES);
CHECK(test.GetBytesReceived() == 128 * JUNGFRAU_PACKET_SIZE_BYTES);
double mean_error = CheckConversion(x, c_in, data.data(), test.GetDeviceOutput(0,0)->pixels);
@@ -390,6 +391,7 @@ TEST_CASE("HLS_C_Simulation_check_convert_full_range", "[FPGA][Full]") {
}
TEST_CASE("HLS_C_Simulation_check_convert_full_range_I32", "[FPGA][Full]") {
Logger logger("HLS_C_Simulation_check_convert_full_range_I32");
std::vector<uint16_t> data(RAW_MODULE_SIZE);
std::vector<double> gain(3 * RAW_MODULE_SIZE);
@@ -410,6 +412,8 @@ TEST_CASE("HLS_C_Simulation_check_convert_full_range_I32", "[FPGA][Full]") {
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::Int32);
REQUIRE(x.GetPhotonEnergy_keV() == Approx(energy));
@@ -430,7 +434,7 @@ TEST_CASE("HLS_C_Simulation_check_convert_full_range_I32", "[FPGA][Full]") {
REQUIRE_NOTHROW(test.OutputStream().read());
REQUIRE(test.OutputStream().size() == 0);
REQUIRE(test.GetBytesReceived() == 128 * JUNGFRAU_PACKET_SIZE_BYTES);
CHECK(test.GetBytesReceived() == 128 * JUNGFRAU_PACKET_SIZE_BYTES);
double mean_error = CheckConversion(x, c_in, data.data(), (int32_t *) test.GetDeviceOutput(0,0)->pixels);
@@ -439,6 +443,7 @@ TEST_CASE("HLS_C_Simulation_check_convert_full_range_I32", "[FPGA][Full]") {
}
TEST_CASE("HLS_C_Simulation_check_convert_full_range_sum4", "[FPGA][Full]") {
Logger logger("HLS_C_Simulation_check_convert_full_range_sum4");
std::vector<uint16_t> data(RAW_MODULE_SIZE);
std::vector<double> gain(3 * RAW_MODULE_SIZE);
@@ -461,6 +466,7 @@ TEST_CASE("HLS_C_Simulation_check_convert_full_range_sum4", "[FPGA][Full]") {
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));
@@ -482,7 +488,7 @@ TEST_CASE("HLS_C_Simulation_check_convert_full_range_sum4", "[FPGA][Full]") {
REQUIRE_NOTHROW(test.OutputStream().read());
REQUIRE(test.OutputStream().size() == 0);
REQUIRE(test.GetBytesReceived() == 128 * nsummation * JUNGFRAU_PACKET_SIZE_BYTES);
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);
@@ -491,6 +497,7 @@ TEST_CASE("HLS_C_Simulation_check_convert_full_range_sum4", "[FPGA][Full]") {
}
TEST_CASE("HLS_C_Simulation_check_convert_full_range_U16", "[FPGA][Full]") {
Logger logger("HLS_C_Simulation_check_convert_full_range_U16");
std::vector<uint16_t> data(RAW_MODULE_SIZE);
std::vector<double> gain(3 * RAW_MODULE_SIZE);
@@ -511,6 +518,7 @@ TEST_CASE("HLS_C_Simulation_check_convert_full_range_U16", "[FPGA][Full]") {
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));
@@ -531,7 +539,7 @@ TEST_CASE("HLS_C_Simulation_check_convert_full_range_U16", "[FPGA][Full]") {
REQUIRE_NOTHROW(test.OutputStream().read());
REQUIRE(test.OutputStream().size() == 0);
REQUIRE(test.GetBytesReceived() == 128 * JUNGFRAU_PACKET_SIZE_BYTES);
CHECK(test.GetBytesReceived() == 128 * JUNGFRAU_PACKET_SIZE_BYTES);
double mean_error = CheckConversion(x, c_in, data.data(), (uint16_t *) test.GetDeviceOutput(0,0)->pixels);
@@ -1257,23 +1265,23 @@ TEST_CASE("HLS_C_Simulation_internal_packet_generator_integration", "[FPGA][Full
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 == 32754LU * (RAW_MODULE_SIZE / 2) * (1LU<<24));
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 == 32754LU * (RAW_MODULE_SIZE / 2 - 1)* (1LU<<24));
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 == 32754LU * (RAW_MODULE_SIZE) * (1LU<<24));
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 == 32754 * (RAW_MODULE_SIZE) * (1LU<<24));
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 == 32754 * (RAW_MODULE_SIZE) * (1LU<<24));
CHECK(integration_result[54].sum == Approx(32754 * (RAW_MODULE_SIZE)));
CHECK(integration_result[54].count == RAW_MODULE_SIZE);
}
@@ -1393,9 +1401,13 @@ TEST_CASE("HLS_C_Simulation_internal_packet_generator_32bit", "[FPGA][Full]") {
for (int image = 0; image < nframes; image++) {
for (int m = 0; m < nmodules; m++) {
REQUIRE(test.Counters().GetCompletion(image, m).timestamp == INT_PKT_GEN_EXPTTIME * image);
REQUIRE(test.Counters().GetCompletion(image, m).bunchid == INT_PKT_GEN_BUNCHID + image);
REQUIRE(test.Counters().GetCompletion(image, m).exptime == INT_PKT_GEN_EXPTTIME);
CHECK(test.GetDeviceOutput(image, m)->module_statistics.frame_number == image);
CHECK(test.GetDeviceOutput(image, m)->module_statistics.packet_count == 128);
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.timestamp == INT_PKT_GEN_EXPTTIME * image);
CHECK(test.GetDeviceOutput(image, m)->module_statistics.bunchid == INT_PKT_GEN_BUNCHID + image);
CHECK(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++) {
@@ -1435,9 +1447,9 @@ TEST_CASE("HLS_C_Simulation_internal_packet_generator_summation", "[FPGA][Full]"
auto test_frame_signed = (uint16_t *) test_frame.data();
for (int image = 0; image < nframes; image++) {
for (int m = 0; m < nmodules; m++) {
REQUIRE(test.Counters().GetCompletion(image, m).timestamp == INT_PKT_GEN_EXPTTIME * image * nsummation);
REQUIRE(test.Counters().GetCompletion(image, m).bunchid == INT_PKT_GEN_BUNCHID + image * nsummation);
REQUIRE(test.Counters().GetCompletion(image, m).exptime == INT_PKT_GEN_EXPTTIME);
REQUIRE(test.GetDeviceOutput(image, m)->module_statistics.timestamp == INT_PKT_GEN_EXPTTIME * image * nsummation);
REQUIRE(test.GetDeviceOutput(image, m)->module_statistics.bunchid == 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++) {
@@ -1446,3 +1458,86 @@ TEST_CASE("HLS_C_Simulation_internal_packet_generator_summation", "[FPGA][Full]"
}
}
}
#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<uint16_t> 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<double> 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.CreatePackets(x, 1, NFRAMES_PEDESTAL_CHECK, 0, data.data(), false);
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);
}
}