Files
Jungfraujoch/fpga/hls_simulation/datamover_model.h
T
leonarski_f cc3eb8352c
Build Packages / Unit tests (push) Skipped
Build Packages / build:rpm (rocky8_nocuda) (push) Successful in 9m28s
Build Packages / build:rpm (rocky9_nocuda) (push) Successful in 10m9s
Build Packages / build:rpm (ubuntu2404_nocuda) (push) Successful in 9m47s
Build Packages / build:rpm (ubuntu2204_nocuda) (push) Successful in 10m58s
Build Packages / build:rpm (rocky8_sls9) (push) Successful in 11m39s
Build Packages / build:rpm (rocky8) (push) Successful in 11m43s
Build Packages / build:rpm (rocky9_sls9) (push) Successful in 12m59s
Build Packages / Generate python client (push) Successful in 35s
Build Packages / Build documentation (push) Successful in 59s
Build Packages / Create release (push) Skipped
Build Packages / build:rpm (ubuntu2204) (push) Successful in 11m48s
Build Packages / build:rpm (rocky9) (push) Successful in 12m32s
Build Packages / build:rpm (ubuntu2404) (push) Successful in 10m24s
Build Packages / XDS test (durin plugin) (push) Successful in 7m35s
Build Packages / XDS test (neggia plugin) (push) Successful in 6m50s
Build Packages / XDS test (JFJoch plugin) (push) Successful in 7m40s
Build Packages / DIALS test (push) Successful in 11m19s
v1.0.0-rc.148 (#58)
This is an UNSTABLE release. The release has significant modifications for data processing - in case of troubles go back to 1.0.0-rc.144.

* jfjoch_broker: Improve azimuthal integration (add <I^2> calculation)
* jfjoch_broker: Fixes around indexing, aiming to handle multi-lattice crystals (work in progress, it is not fully integrated)
* jfjoch_writer: Save mean(I), stddev(I), and count(I) for each azimuthal bin

Reviewed-on: #58
2026-06-08 08:30:35 +02:00

96 lines
3.4 KiB
C++

// SPDX-FileCopyrightText: 2024 Filip Leonarski, Paul Scherrer Institute <filip.leonarski@psi.ch>
// SPDX-License-Identifier: GPL-3.0-only
#pragma once
#include <thread>
#include "../hls/hls_jfjoch.h"
enum class Direction {Input, Output};
template <int N, int DEPTH=0> class Datamover {
volatile int stop_signal;
Direction dir;
char *offset;
hls::stream<axis_datamover_ctrl> control;
hls::stream<ap_axiu<N,1,1,1>, DEPTH> data;
std::thread datamover_thread;
size_t bytes_transferred;
std::atomic<uint32_t> descriptors_done = 0;
void Move() {
axis_datamover_ctrl command = control.read();
uint64_t addr = command.data(31+64,32);
uint32_t bytes = command.data(22,0);
if (bytes % (N/8) != 0)
throw std::runtime_error("AXI datamover transfer must be aligned to " + std::to_string(N/8) + " bytes");
if (addr % (N/8) != 0)
throw std::runtime_error("AXI datamover addr must be aligned to " + std::to_string(N/8) + " bytes");
if (bytes == 0)
throw std::runtime_error("AXI datamover transfer cannot be 0");
uint32_t xfers = bytes / (N/8);
auto host_mem = (ap_uint<N> *) (offset + addr);
ap_axiu<N,1,1,1> data_packet;
if (dir == Direction::Input) {
for (uint64_t i = 0; i < xfers; i++) {
data_packet.data = host_mem[i];
for (int j = 0; j < N / 8; j++)
data_packet.keep[j] = 1;
data_packet.last = ((i == xfers - 1) ? 1 : 0);
data << data_packet;
bytes_transferred += N/8;
}
} else {
for (uint64_t i = 0; i < xfers; i++) {
data >> data_packet;
host_mem[i] = data_packet.data;
for (int j = 0; j < N / 8; j++) {
if (data_packet.keep[j] != 1)
throw std::runtime_error("TKEEP set low for bit " + std::to_string(i));
}
if (data_packet.last != ((i == xfers - 1) ? 1 : 0))
throw std::runtime_error("TLAST packet flag set incorrectly for packet " + std::to_string(i) + " Expected xfers: " + std::to_string(xfers));
bytes_transferred += N/8;
}
}
descriptors_done++;
}
public:
void Run() {
while (!stop_signal || !control.empty()) {
while (!stop_signal && control.empty())
std::this_thread::sleep_for(std::chrono::milliseconds(1));
// All commands that arrive till stop signal is executed, are executed
while (!control.empty()) {
Move();
}
}
};
size_t Stop() noexcept { stop_signal = true; datamover_thread.join(); return bytes_transferred; }
Datamover(Direction in_dir, char* in_offset)
: dir(in_dir), offset(in_offset), stop_signal(0), bytes_transferred(0) {
datamover_thread = std::thread([this] {this->Run(); });
};
bool IsIdle() const {
return control.empty();
}
uint32_t GetCompletedDescriptors() const {
return descriptors_done;
}
void ClearCompletedDescriptors() {
descriptors_done = 0;
}
hls::stream<axis_datamover_ctrl>& GetCtrlStream() { return control; }
hls::stream<ap_axiu<N,1,1,1> >& GetDataStream() { return data; }
~Datamover() { Stop(); }
};