mirror of
https://github.com/paulscherrerinstitute/sf_daq_buffer.git
synced 2026-05-05 22:44:13 +02:00
Externalize image assembly from RamBuffer
This commit is contained in:
@@ -5,34 +5,29 @@
|
||||
#include "formats.hpp"
|
||||
|
||||
class RamBuffer {
|
||||
const std::string detector_name_;
|
||||
const std::string buffer_name_;
|
||||
const int n_modules_;
|
||||
const int n_submodules_;
|
||||
const int n_slots_;
|
||||
const int bit_depth_;
|
||||
|
||||
const size_t n_packets_per_frame_;
|
||||
const size_t data_bytes_per_frame_;
|
||||
|
||||
const size_t meta_bytes_;
|
||||
const size_t image_bytes_;
|
||||
const size_t data_bytes_;
|
||||
const size_t slot_bytes_;
|
||||
const size_t buffer_bytes_;
|
||||
|
||||
int shm_fd_;
|
||||
void* buffer_;
|
||||
char* buffer_;
|
||||
|
||||
ModuleFrame* meta_buffer_;
|
||||
char* image_buffer_;
|
||||
|
||||
private:
|
||||
void assemble_eiger_image(ImageMetadata &image_meta,
|
||||
const int bit_depth, const size_t slot_n) const;
|
||||
private:
|
||||
char* _get_meta_buffer(int slot_n, uint64_t module_id) const;
|
||||
char* _get_frame_data_buffer(int slot_n, uint64_t module_id) const;
|
||||
|
||||
public:
|
||||
RamBuffer(const std::string& detector_name,
|
||||
const int n_modules,
|
||||
const int n_submodules,
|
||||
const int bit_depth);
|
||||
RamBuffer(const std::string& buffer_name,
|
||||
size_t meta_n_bytes,
|
||||
size_t data_n_bytes,
|
||||
int n_modules,
|
||||
int n_slots);
|
||||
|
||||
~RamBuffer();
|
||||
|
||||
void write_frame(const ModuleFrame &src_meta, const char *src_data) const;
|
||||
@@ -40,10 +35,14 @@ public:
|
||||
const uint64_t module_id,
|
||||
ModuleFrame &meta,
|
||||
char *data) const;
|
||||
char* read_image(const uint64_t pulse_id) const;
|
||||
void assemble_image(
|
||||
const uint64_t pulse_id, ImageMetadata &image_meta) const;
|
||||
|
||||
|
||||
char* get_frame_data(
|
||||
const uint64_t image_id, const uint64_t module_id) const;
|
||||
char* get_image_data(const uint64_t image_id) const;
|
||||
char* get_frame_meta(
|
||||
const uint64_t image_id, const uint64_t module_id) const;
|
||||
char* get_image_meta(const uint64_t image_id) const;
|
||||
|
||||
|
||||
|
||||
};
|
||||
|
||||
+62
-272
@@ -14,34 +14,32 @@
|
||||
using namespace std;
|
||||
using namespace buffer_config;
|
||||
|
||||
RamBuffer::RamBuffer(
|
||||
const string &detector_name,
|
||||
const int n_modules,
|
||||
const int n_submodules,
|
||||
const int bit_depth) :
|
||||
detector_name_(detector_name),
|
||||
RamBuffer::RamBuffer(const string& buffer_name,
|
||||
const size_t meta_n_bytes,
|
||||
const size_t data_n_bytes,
|
||||
const int n_modules = 1,
|
||||
const int n_slots = buffer_config::RAM_BUFFER_N_SLOTS) :
|
||||
buffer_name_(buffer_name),
|
||||
n_modules_(n_modules),
|
||||
n_submodules_(n_submodules_),
|
||||
bit_depth_(bit_depth),
|
||||
n_slots_(buffer_config::RAM_BUFFER_N_SLOTS),
|
||||
meta_bytes_(sizeof(ModuleFrame) * n_modules_),
|
||||
n_packets_per_frame_(bit_depth_ * MODULE_N_PIXELS / 8 / DATA_BYTES_PER_PACKET / n_modules * n_submodules),
|
||||
data_bytes_per_frame_(n_packets_per_frame_ * DATA_BYTES_PER_PACKET),
|
||||
image_bytes_(MODULE_N_BYTES * n_modules_),
|
||||
buffer_bytes_((meta_bytes_ + image_bytes_) * n_slots_)
|
||||
n_slots_(n_slots),
|
||||
meta_bytes_(meta_n_bytes),
|
||||
data_bytes_(data_n_bytes),
|
||||
slot_bytes_((meta_bytes_ + data_bytes_) * n_modules),
|
||||
buffer_bytes_(slot_bytes_ * n_slots_)
|
||||
{
|
||||
#ifdef DEBUG_OUTPUT
|
||||
using namespace date;
|
||||
cout << " [" << std::chrono::system_clock::now();
|
||||
cout << "] [RamBuffer::RamBuffer] :";
|
||||
cout << " || buffer_name_ " << buffer_name;
|
||||
cout << " || n_modules_ " << n_modules_;
|
||||
cout << " || n_slots_ " << n_slots_;
|
||||
cout << " || meta_bytes_" << meta_bytes_;
|
||||
cout << " || data_bytes_" << data_bytes_;
|
||||
cout << endl;
|
||||
#endif
|
||||
|
||||
#ifdef DEBUG_OUTPUT
|
||||
using namespace date;
|
||||
cout << " [" << std::chrono::system_clock::now();
|
||||
cout << "] [RamBuffer::Constructor] :";
|
||||
cout << " || bit_depth_ " << bit_depth_;
|
||||
cout << " || n_packets_per_frame_ " << n_packets_per_frame_;
|
||||
cout << " || image_bytes_ " << image_bytes_;
|
||||
cout << " || data_bytes_per_frame_ " << data_bytes_per_frame_;
|
||||
cout << endl;
|
||||
#endif
|
||||
shm_fd_ = shm_open(detector_name_.c_str(), O_RDWR | O_CREAT, 0777);
|
||||
shm_fd_ = shm_open(buffer_name_.c_str(), O_RDWR | O_CREAT, 0777);
|
||||
if (shm_fd_ < 0) {
|
||||
throw runtime_error(strerror(errno));
|
||||
}
|
||||
@@ -51,38 +49,44 @@ RamBuffer::RamBuffer(
|
||||
}
|
||||
|
||||
// TODO: Test with MAP_HUGETLB
|
||||
buffer_ = mmap(NULL, buffer_bytes_, PROT_WRITE, MAP_SHARED, shm_fd_, 0);
|
||||
buffer_ = static_cast<char *>(mmap(NULL, buffer_bytes_, PROT_WRITE,
|
||||
MAP_SHARED, shm_fd_, 0));
|
||||
if (buffer_ == MAP_FAILED) {
|
||||
throw runtime_error(strerror(errno));
|
||||
}
|
||||
|
||||
// Metadata buffer is located at the start of the memory region.
|
||||
meta_buffer_ = (ModuleFrame *) buffer_;
|
||||
// Image buffer start right after metadata buffer.
|
||||
image_buffer_ = (char*)buffer_ + (meta_bytes_ * n_slots_);
|
||||
}
|
||||
|
||||
RamBuffer::~RamBuffer()
|
||||
{
|
||||
munmap(buffer_, buffer_bytes_);
|
||||
close(shm_fd_);
|
||||
shm_unlink(detector_name_.c_str());
|
||||
shm_unlink(buffer_name_.c_str());
|
||||
}
|
||||
|
||||
char* RamBuffer::_get_meta_buffer(
|
||||
int slot_n,
|
||||
uint64_t module_id) const
|
||||
{
|
||||
return buffer_ + (slot_n * slot_bytes_) +
|
||||
(module_id * meta_bytes_);
|
||||
}
|
||||
|
||||
char* RamBuffer::_get_frame_data_buffer(
|
||||
int slot_n,
|
||||
uint64_t module_id) const
|
||||
{
|
||||
return buffer_ + (slot_n * slot_bytes_) +
|
||||
(n_modules_ * meta_bytes_) + (module_id * data_bytes_);
|
||||
}
|
||||
|
||||
void RamBuffer::write_frame(
|
||||
const ModuleFrame& src_meta,
|
||||
const char *src_data) const
|
||||
{
|
||||
|
||||
const int slot_n = src_meta.frame_index % n_slots_;
|
||||
|
||||
ModuleFrame *dst_meta = meta_buffer_ +
|
||||
(n_modules_ * slot_n) +
|
||||
src_meta.module_id;
|
||||
|
||||
char *dst_data = image_buffer_ +
|
||||
(image_bytes_ * slot_n) +
|
||||
(data_bytes_per_frame_ * src_meta.module_id);
|
||||
auto *dst_meta = (ModuleFrame*) get_frame_meta(
|
||||
src_meta.pulse_id, src_meta.module_id);
|
||||
auto *dst_data = get_frame_data(
|
||||
src_meta.pulse_id, src_meta.module_id);
|
||||
|
||||
#ifdef DEBUG_OUTPUT
|
||||
using namespace date;
|
||||
@@ -92,249 +96,35 @@ void RamBuffer::write_frame(
|
||||
cout << " || src_meta.n_recv_packets " << src_meta.n_recv_packets;
|
||||
cout << " || src_meta.daq_rec " << src_meta.daq_rec;
|
||||
cout << " || src_meta.module_id " << src_meta.module_id;
|
||||
cout << " || slot_n " << slot_n;
|
||||
cout << endl;
|
||||
#endif
|
||||
|
||||
memcpy(dst_meta, &src_meta, sizeof(ModuleFrame));
|
||||
memcpy(dst_data, src_data, data_bytes_per_frame_);
|
||||
memcpy(dst_data, src_data, data_bytes_);
|
||||
}
|
||||
|
||||
void RamBuffer::read_frame(
|
||||
const uint64_t pulse_id,
|
||||
const uint64_t module_id,
|
||||
ModuleFrame& dst_meta,
|
||||
char* dst_data) const
|
||||
char* RamBuffer::get_frame_meta(
|
||||
const uint64_t image_id,
|
||||
const uint64_t module_id) const
|
||||
{
|
||||
const size_t slot_n = pulse_id % n_slots_;
|
||||
|
||||
ModuleFrame *src_meta = meta_buffer_ + (n_modules_ * slot_n) + module_id;
|
||||
|
||||
char *src_data = image_buffer_ +
|
||||
(image_bytes_ * slot_n) +
|
||||
(MODULE_N_BYTES * module_id);
|
||||
|
||||
memcpy(&dst_meta, src_meta, sizeof(ModuleFrame));
|
||||
memcpy(dst_data, src_data, MODULE_N_BYTES);
|
||||
const size_t slot_n = image_id % n_slots_;
|
||||
return _get_meta_buffer(slot_n, module_id);
|
||||
}
|
||||
|
||||
void RamBuffer::assemble_image(
|
||||
const uint64_t pulse_id, ImageMetadata &image_meta) const
|
||||
char* RamBuffer::get_image_meta(const uint64_t image_id) const
|
||||
{
|
||||
const size_t slot_n = pulse_id % n_slots_;
|
||||
|
||||
ModuleFrame *src_meta = meta_buffer_ + (n_modules_ * slot_n);
|
||||
#ifdef DEBUG_OUTPUT
|
||||
using namespace date;
|
||||
cout << " [" << std::chrono::system_clock::now();
|
||||
cout << "] [RamBuffer::assemble_image] :";
|
||||
cout << " pulse_id : " << pulse_id;
|
||||
cout << endl;
|
||||
#endif
|
||||
|
||||
auto is_pulse_init = false;
|
||||
auto is_good_image = true;
|
||||
|
||||
// for each module it collects the metadata from each frame
|
||||
// and verifies if is a good frame
|
||||
for (int i_module=0; i_module < n_modules_; i_module++) {
|
||||
ModuleFrame *frame_meta = src_meta + i_module;
|
||||
|
||||
#ifdef DEBUG_OUTPUT
|
||||
using namespace date;
|
||||
cout << " [" << std::chrono::system_clock::now();
|
||||
cout << "] module_id: " << i_module;
|
||||
cout << " || frame index: " << frame_meta->frame_index;
|
||||
cout << " || pulse index: " << frame_meta->pulse_id;
|
||||
cout << " || row: " << frame_meta->row;
|
||||
cout << " || column: " << frame_meta->column;
|
||||
cout << " || n_recv_packets: " << frame_meta->n_recv_packets;
|
||||
cout << endl;
|
||||
#endif
|
||||
|
||||
auto is_good_frame =
|
||||
frame_meta->n_recv_packets == n_packets_per_frame_;
|
||||
|
||||
if (!is_good_frame) {
|
||||
is_good_image = false;
|
||||
#ifdef DEBUG_OUTPUT
|
||||
using namespace date;
|
||||
cout << " [" << std::chrono::system_clock::now();
|
||||
cout << "] [RamBuffer::assemble_image] ";
|
||||
cout << " not a good frame " << is_good_frame;
|
||||
cout << "n_recv_packets != n_packets_per_frame_";
|
||||
cout << endl;
|
||||
#endif
|
||||
continue;
|
||||
}
|
||||
// in the first module will enter here and define image metadata
|
||||
if (!is_pulse_init) {
|
||||
if (frame_meta->frame_index != pulse_id) {
|
||||
stringstream err_msg;
|
||||
err_msg << "[RamBuffer::assemble_image]";
|
||||
err_msg << " Unexpected pulse_id in ram buffer.";
|
||||
err_msg << " expected=" << pulse_id;
|
||||
err_msg << " got=" << frame_meta->pulse_id;
|
||||
|
||||
for (int i = 0; i < n_modules_; i++) {
|
||||
ModuleFrame *meta = src_meta + i_module;
|
||||
|
||||
err_msg << " (module " << i << ", ";
|
||||
err_msg << meta->pulse_id << "),";
|
||||
}
|
||||
err_msg << endl;
|
||||
|
||||
throw runtime_error(err_msg.str());
|
||||
}
|
||||
|
||||
image_meta.pulse_id = frame_meta->pulse_id;
|
||||
image_meta.frame_index = frame_meta->frame_index;
|
||||
image_meta.daq_rec = frame_meta->daq_rec;
|
||||
#ifdef DEBUG_OUTPUT
|
||||
using namespace date;
|
||||
cout << " [" << std::chrono::system_clock::now();
|
||||
cout << "] [RamBuffer::assemble_image] :";
|
||||
cout << " Defining image_meta";
|
||||
cout << " || image_meta.frame_index " << image_meta.frame_index;
|
||||
cout << endl;
|
||||
#endif
|
||||
is_pulse_init = 1;
|
||||
}
|
||||
|
||||
if (is_good_image) {
|
||||
if (frame_meta->pulse_id != image_meta.pulse_id) {
|
||||
is_good_image = false;
|
||||
#ifdef DEBUG_OUTPUT
|
||||
using namespace date;
|
||||
cout << " [" << std::chrono::system_clock::now();
|
||||
cout << "] [RamBuffer::assemble_image] ";
|
||||
cout << "not good image";
|
||||
cout << "frame_meta->pulse_id != image_meta.pulse_id";
|
||||
cout << endl;
|
||||
#endif
|
||||
|
||||
// TODO: Add some diagnostics in case this happens.
|
||||
}
|
||||
|
||||
if (frame_meta->frame_index != image_meta.frame_index) {
|
||||
is_good_image = false;
|
||||
#ifdef DEBUG_OUTPUT
|
||||
using namespace date;
|
||||
cout << " [" << std::chrono::system_clock::now();
|
||||
cout << "] [RamBuffer::assemble_image] !is_pulse_init:";
|
||||
cout << "frame_meta->frame_index != image_meta.frame_index";
|
||||
cout << endl;
|
||||
#endif
|
||||
}
|
||||
|
||||
if (frame_meta->daq_rec != image_meta.daq_rec) {
|
||||
is_good_image = false;
|
||||
#ifdef DEBUG_OUTPUT
|
||||
using namespace date;
|
||||
cout << " [" << std::chrono::system_clock::now();
|
||||
cout << "] [RamBuffer::assemble_image] !is_pulse_init:";
|
||||
cout << "frame_meta->daq_rec != image_meta.daq_rec";
|
||||
cout << endl;
|
||||
#endif
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
image_meta.is_good_image = is_good_image;
|
||||
|
||||
// bad practice, what'd be the nicest way to do this?
|
||||
#ifdef USE_EIGER
|
||||
if (is_good_image){
|
||||
assemble_eiger_image(image_meta, bit_depth_, slot_n);
|
||||
}
|
||||
#endif
|
||||
|
||||
if (!is_pulse_init) {
|
||||
image_meta.pulse_id = 0;
|
||||
image_meta.frame_index = 0;
|
||||
image_meta.daq_rec = 0;
|
||||
}
|
||||
return get_frame_meta(image_id, 0);
|
||||
}
|
||||
|
||||
char* RamBuffer::read_image(const uint64_t pulse_id) const
|
||||
char* RamBuffer::get_frame_data(
|
||||
const uint64_t image_id,
|
||||
const uint64_t module_id) const
|
||||
{
|
||||
const size_t slot_n = pulse_id % n_slots_;
|
||||
char *src_data = image_buffer_ + (image_bytes_ * slot_n);
|
||||
|
||||
return src_data;
|
||||
const size_t slot_n = image_id % n_slots_;
|
||||
return _get_frame_data_buffer(slot_n, module_id);
|
||||
}
|
||||
|
||||
void RamBuffer::assemble_eiger_image(ImageMetadata &image_meta, const int bit_depth, const size_t slot_n) const
|
||||
char* RamBuffer::get_image_data(const uint64_t image_id) const
|
||||
{
|
||||
|
||||
const uint32_t n_bytes_per_module_line = N_BYTES_PER_MODULE_LINE(bit_depth);
|
||||
const uint32_t n_bytes_per_gap = GAP_X_MODULE_PIXELS * bit_depth / 8;
|
||||
const uint32_t n_bytes_per_image_line = n_bytes_per_module_line * 2 + n_bytes_per_gap;
|
||||
const int n_lines_per_frame = DATA_BYTES_PER_PACKET / n_bytes_per_module_line * n_packets_per_frame_;
|
||||
|
||||
#ifdef DEBUG_OUTPUT
|
||||
using namespace date;
|
||||
cout << " [" << std::chrono::system_clock::now();
|
||||
cout << "] [RamBuffer::is_good_image] ";
|
||||
cout << " image_meta.frame_index" << image_meta.frame_index;
|
||||
cout << " Verification: " << endl;
|
||||
cout << " || n_bytes_per_module_line " << n_bytes_per_module_line << endl;
|
||||
cout << " || n_bytes_per_gap " << n_bytes_per_gap << endl;
|
||||
cout << " || n_bytes_per_image_line " << n_bytes_per_image_line;
|
||||
cout << " || n_lines_per_frame " << n_lines_per_frame << endl;;
|
||||
#endif
|
||||
for (int i_module=0; i_module < n_modules_; i_module++) {
|
||||
// defines from which eiger module this submodule is part
|
||||
const int eiger_module_index = i_module / n_submodules_;
|
||||
// module frame metadata
|
||||
ModuleFrame *frame_meta = meta_buffer_ + (n_modules_ * slot_n) + i_module;
|
||||
// module frame data
|
||||
char *frame_data = image_buffer_ + (image_bytes_ * slot_n) + (data_bytes_per_frame_ * i_module);
|
||||
// top
|
||||
uint32_t source_offset = 0;
|
||||
uint32_t reverse_factor = 0;
|
||||
uint32_t bottom_offset = 0;
|
||||
uint32_t line_number = 0;
|
||||
uint32_t dest_line_offset=0;
|
||||
|
||||
// If bottom -> reversed
|
||||
const auto reverse = IS_BOTTOM(frame_meta->row);
|
||||
if (reverse == -1){
|
||||
line_number = MODULE_Y_SIZE + GAP_Y_MODULE_PIXELS;
|
||||
reverse_factor = MODULE_Y_SIZE - 1;
|
||||
dest_line_offset += n_bytes_per_image_line * (MODULE_Y_SIZE + GAP_Y_MODULE_PIXELS);
|
||||
}
|
||||
|
||||
const auto i_module_row = frame_meta->row;
|
||||
const auto i_module_column = frame_meta->column;
|
||||
|
||||
uint32_t dest_module_line = line_number;
|
||||
|
||||
if (i_module_column == 1){
|
||||
source_offset += MODULE_X_SIZE + GAP_X_MODULE_PIXELS;
|
||||
dest_line_offset += n_bytes_per_module_line + n_bytes_per_gap;
|
||||
}
|
||||
|
||||
for (uint32_t frame_line=0; frame_line < n_lines_per_frame; frame_line++)
|
||||
{
|
||||
// Copy each chip line individually, to allow a gap of n_bytes_per_chip_gap in the destination memory.
|
||||
memcpy (
|
||||
(char*)(image_buffer_ + (image_bytes_ * slot_n)) + dest_line_offset,
|
||||
(char*) frame_data + source_offset,
|
||||
n_bytes_per_module_line
|
||||
);
|
||||
|
||||
memcpy (
|
||||
(char*)(image_buffer_ + (image_bytes_ * slot_n)) + dest_line_offset + n_bytes_per_module_line,
|
||||
(char*) frame_data + source_offset + n_bytes_per_module_line,
|
||||
n_bytes_per_module_line
|
||||
);
|
||||
|
||||
source_offset += n_bytes_per_module_line;
|
||||
dest_line_offset += reverse * n_bytes_per_image_line;
|
||||
}
|
||||
line_number += n_lines_per_frame;
|
||||
dest_module_line = line_number + n_lines_per_frame - 1;
|
||||
}
|
||||
|
||||
}
|
||||
return get_frame_data(image_id, 0);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user