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
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
96 lines
3.4 KiB
C++
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(); }
|
|
};
|