DUNE-DAQ
DUNE Trigger and Data Acquisition software
Toggle main menu visibility
Loading...
Searching...
No Matches
dunedaq
sourcecode
flxlibs
src
CardWrapper.cpp
Go to the documentation of this file.
1
8
// From Module
9
#include "
CardWrapper.hpp
"
10
#include "
FelixDefinitions.hpp
"
11
#include "
FelixIssues.hpp
"
12
13
#include "
logging/Logging.hpp
"
14
15
#include "flxcard/FlxException.h"
16
#include "packetformat/block_format.hpp"
17
18
// From STD
19
#include <chrono>
20
#include <memory>
21
#include <string>
22
26
enum
27
{
28
TLVL_ENTER_EXIT_METHODS
= 5,
29
TLVL_WORK_STEPS
= 10,
30
TLVL_BOOKKEEPING
= 15
31
};
32
33
namespace
dunedaq
{
34
namespace
flxlibs
{
35
36
CardWrapper::CardWrapper
(
const
appmodel::FelixInterface
* cfg, std::vector<unsigned int> enabled_links)
37
:
m_run_marker
{ false }
38
,
m_card_id
(cfg->get_card())
39
,
m_logical_unit
(cfg->get_slr())
40
,
m_dma_id
(cfg->get_dma_id())
41
,
m_margin_blocks
(cfg->get_dma_margin_blocks())
42
,
m_block_threshold
(cfg->get_dma_block_threshold())
43
,
m_interrupt_mode
(cfg->get_interrupt_mode())
44
,
m_poll_time
(cfg->get_poll_time())
45
,
m_numa_id
(cfg->get_numa_id())
46
,
m_info_str
(
""
)
47
,
m_run_lock
{ false }
48
,
m_dma_processor
(0)
49
,
m_handle_block_addr
(nullptr)
50
,
m_links_enabled
(enabled_links)
51
{
52
m_dma_memory_size
= cfg->
get_dma_memory_size_gb
() * 1024 * 1024 * 1024UL;
53
54
std::ostringstream tnoss;
55
tnoss <<
m_dma_processor_name
<<
"-"
<< std::to_string(
m_card_id
);
// append physical card id
56
m_dma_processor
.
set_name
(tnoss.str(),
m_logical_unit
);
// set_name appends logical unit id
57
58
std::ostringstream cardoss;
59
cardoss <<
"[id:"
<< std::to_string(
m_card_id
) <<
" slr:"
<< std::to_string(
m_logical_unit
) <<
"]"
;
60
m_card_id_str
= cardoss.str();
61
62
m_flx_card
= std::make_unique<FlxCard>();
63
if
(
m_flx_card
==
nullptr
) {
64
throw
flxlibs::CardError(
ERS_HERE
,
"Couldn't create FlxCard object."
);
65
}
66
}
67
68
CardWrapper::~CardWrapper
()
69
{
70
TLOG_DEBUG
(
TLVL_ENTER_EXIT_METHODS
) <<
"CardWrapper destructor called. First stop check, then closing card."
;
71
graceful_stop
();
72
close_card
();
73
TLOG_DEBUG
(
TLVL_ENTER_EXIT_METHODS
) <<
"CardWrapper destroyed."
;
74
}
75
76
void
77
CardWrapper::configure
()
78
{
79
if
(
m_configured
) {
80
TLOG_DEBUG
(
TLVL_ENTER_EXIT_METHODS
) <<
"Card is already configured! Won't touch it."
;
81
}
else
{
82
TLOG_DEBUG
(
TLVL_WORK_STEPS
) <<
"Configuring CardWrapper of card "
<<
m_card_id_str
;
83
// Open card
84
open_card
();
85
TLOG_DEBUG
(
TLVL_WORK_STEPS
) <<
"Card["
<<
m_card_id_str
<<
"] opened."
;
86
// Allocate CMEM
87
m_cmem_handle
=
allocate_CMEM
(
m_numa_id
,
m_dma_memory_size
, &
m_phys_addr
, &
m_virt_addr
);
88
TLOG_DEBUG
(
TLVL_WORK_STEPS
) <<
"Card["
<<
m_card_id_str
<<
"] CMEM memory allocated with "
89
<< std::to_string(
m_dma_memory_size
) <<
" Bytes."
;
90
// Stop currently running DMA
91
stop_DMA
();
92
TLOG_DEBUG
(
TLVL_WORK_STEPS
) <<
"Card["
<<
m_card_id_str
<<
"] DMA interactions force stopped."
;
93
// Init DMA between software and card
94
init_DMA
();
95
TLOG_DEBUG
(
TLVL_WORK_STEPS
) <<
"Card["
<<
m_card_id_str
<<
"] DMA access initialized."
;
96
// The rest was some CPU pinning.
97
TLOG_DEBUG
(
TLVL_WORK_STEPS
) <<
m_card_id_str
<<
"] is configured for datataking."
;
98
m_configured
=
true
;
99
}
100
}
101
102
void
103
CardWrapper::start
()
104
{
105
TLOG_DEBUG
(
TLVL_ENTER_EXIT_METHODS
) <<
"Starting CardWrapper of card "
<<
m_card_id_str
<<
"..."
;
106
if
(!
m_run_marker
.load()) {
107
if
(!
m_block_addr_handler_available
) {
108
TLOG
() <<
"Block Address handler is not set! Is it intentional?"
;
109
}
110
start_DMA
();
111
set_running
(
true
);
112
m_dma_processor
.
set_work
(&
CardWrapper::process_DMA
,
this
);
113
TLOG
() <<
"Started CardWrapper of card "
<<
m_card_id_str
<<
"..."
;
114
}
else
{
115
TLOG
() <<
"CardWrapper of card "
<<
m_card_id_str
<<
" is already running!"
;
116
}
117
}
118
119
void
120
CardWrapper::graceful_stop
()
121
{
122
TLOG_DEBUG
(
TLVL_ENTER_EXIT_METHODS
) <<
"Stopping CardWrapper of card "
<<
m_card_id_str
<<
"..."
;
123
if
(
m_run_marker
.load()) {
124
set_running
(
false
);
125
while
(!
m_dma_processor
.
get_readiness
()) {
126
std::this_thread::sleep_for(std::chrono::milliseconds(10));
127
}
128
stop_DMA
();
129
init_DMA
();
130
TLOG
() <<
"Stopped CardWrapper of card "
<<
m_card_id_str
<<
"!"
;
131
}
else
{
132
TLOG
() <<
"CardWrapper of card "
<<
m_card_id_str
<<
" is already stopped!"
;
133
}
134
}
135
136
void
137
CardWrapper::stop
()
138
{
139
graceful_stop
();
140
}
141
142
void
143
CardWrapper::set_running
(
bool
should_run)
144
{
145
bool
was_running =
m_run_marker
.exchange(should_run);
146
TLOG_DEBUG
(
TLVL_WORK_STEPS
) <<
"Active state was toggled from "
<< was_running <<
" to "
<< should_run;
147
}
148
149
void
150
CardWrapper::open_card
()
151
{
152
TLOG_DEBUG
(
TLVL_WORK_STEPS
) <<
"Opening FELIX card (with DMA lock mask)"
<<
m_card_id_str
;
153
try
{
154
m_card_mutex
.lock();
155
auto
absolute_card_id =
m_card_id
+
m_logical_unit
;
156
u_int current_lock_mask =
m_flx_card
->get_lock_mask(absolute_card_id);
157
TLOG_DEBUG
(
TLVL_WORK_STEPS
) <<
"Current lock mask for FELIX card "
<<
m_card_id_str
158
<<
" mask:"
<< int(current_lock_mask);
159
u_int to_lock_mask = u_int(
m_dma_id
+ 1);
160
if
(current_lock_mask & to_lock_mask) {
// LOCK_NONE=0, LOCK_DMA0=1, LOCK_DMA1=2 from FlxCard.h
161
ers::fatal
(flxlibs::CardError(
ERS_HERE
,
"FELIX card's DMA is locked by another process!"
));
162
exit(EXIT_FAILURE);
163
}
164
m_flx_card
->card_open(
static_cast<
int
>
(absolute_card_id), to_lock_mask);
// FlxCard.h
165
m_card_mutex
.unlock();
166
}
catch
(FlxException& ex) {
167
ers::error
(flxlibs::CardError(
ERS_HERE
, ex.what()));
168
exit(EXIT_FAILURE);
169
}
170
}
171
172
void
173
CardWrapper::close_card
()
174
{
175
TLOG_DEBUG
(
TLVL_WORK_STEPS
) <<
"Closing FELIX card "
<<
m_card_id_str
;
176
try
{
177
m_card_mutex
.lock();
178
m_flx_card
->card_close();
179
m_card_mutex
.unlock();
180
}
catch
(FlxException& ex) {
181
ers::error
(flxlibs::CardError(
ERS_HERE
, ex.what()));
182
exit(EXIT_FAILURE);
183
}
184
}
185
186
int
187
CardWrapper::allocate_CMEM
(uint8_t numa, u_long bsize, u_long* paddr, u_long* vaddr)
// NOLINT
188
{
189
TLOG_DEBUG
(
TLVL_WORK_STEPS
) <<
"Allocating CMEM buffer "
<<
m_card_id_str
<<
" dma id:"
<< std::to_string(
m_dma_id
);
190
int
handle;
191
unsigned
ret = CMEM_Open();
// cmem_rcc.h
192
if
(!ret) {
193
ret = CMEM_NumaSegmentAllocate(bsize, numa,
const_cast<
char
*
>
(
m_card_id_str
.c_str()), &handle);
// NUMA aware
194
// ret = CMEM_GFPBPASegmentAllocate(bsize, const_cast<char*>(m_card_id_str.c_str()), &handle); // non NUMA aware
195
}
196
if
(!ret) {
197
ret = CMEM_SegmentPhysicalAddress(handle, paddr);
198
}
199
if
(!ret) {
200
ret = CMEM_SegmentVirtualAddress(handle, vaddr);
201
}
202
if
(ret) {
203
// rcc_error_print(stdout, ret);
204
m_card_mutex
.lock();
205
m_flx_card
->card_close();
206
m_card_mutex
.unlock();
207
ers::fatal
(
208
flxlibs::CardError(
ERS_HERE
,
209
"Not enough CMEM memory allocated or the application demands too much CMEM memory.\n"
210
"Fix the CMEM memory reservation in the driver or change the module's configuration."
));
211
exit(EXIT_FAILURE);
212
}
213
return
handle;
214
}
215
216
void
217
CardWrapper::init_DMA
()
218
{
219
TLOG_DEBUG
(
TLVL_WORK_STEPS
) <<
"InitDMA issued..."
;
220
m_card_mutex
.lock();
221
m_flx_card
->dma_reset();
222
TLOG_DEBUG
(
TLVL_WORK_STEPS
) <<
"flxCard.dma_reset issued."
;
223
m_flx_card
->soft_reset();
224
TLOG_DEBUG
(
TLVL_WORK_STEPS
) <<
"flxCard.soft_reset issued."
;
225
m_flx_card
->irq_reset_counters();
226
TLOG_DEBUG
(
TLVL_WORK_STEPS
) <<
"flxCard.irq_reset_counters issued."
;
227
// interrupted or polled DMA processing
228
if
(
m_interrupt_mode
) {
229
#if REGMAP_VERSION < 0x500
230
m_flx_card
->irq_enable(
IRQ_DATA_AVAILABLE
);
231
#else
232
m_flx_card
->irq_enable(
IRQ_DATA_AVAILABLE
+
m_dma_id
);
233
#endif
234
TLOG_DEBUG
(
TLVL_WORK_STEPS
) <<
"flxCard.irq_enable issued."
;
235
}
else
{
236
m_flx_card
->irq_disable();
237
TLOG_DEBUG
(
TLVL_WORK_STEPS
) <<
"flxCard.irq_disable issued."
;
238
}
239
m_card_mutex
.unlock();
240
m_current_addr
=
m_phys_addr
;
241
m_destination
=
m_phys_addr
;
242
m_read_index
= 0;
243
TLOG_DEBUG
(
TLVL_WORK_STEPS
) <<
"flxCard initDMA done card["
<<
m_card_id_str
<<
"]"
;
244
}
245
246
void
247
CardWrapper::start_DMA
()
248
{
249
TLOG_DEBUG
(
TLVL_WORK_STEPS
) <<
"Issuing flxCard.dma_to_host for card "
<<
m_card_id_str
250
<<
" dma id:"
<< std::to_string(
m_dma_id
);
251
m_card_mutex
.lock();
252
m_flx_card
->dma_to_host(
m_dma_id
,
m_phys_addr
,
m_dma_memory_size
,
m_dma_wraparound
);
// FlxCard.h
253
m_card_mutex
.unlock();
254
}
255
256
void
257
CardWrapper::stop_DMA
()
258
{
259
TLOG_DEBUG
(
TLVL_WORK_STEPS
) <<
"Issuing flxCard.dma_stop for card "
<<
m_card_id_str
260
<<
" dma id:"
<< std::to_string(
m_dma_id
);
261
m_card_mutex
.lock();
262
m_flx_card
->dma_stop(
m_dma_id
);
263
m_card_mutex
.unlock();
264
}
265
266
inline
uint64_t
// NOLINT
267
CardWrapper::bytes_available
()
268
{
269
return
(
m_current_addr
- ((
m_read_index
*
m_block_size
) +
m_phys_addr
) +
m_dma_memory_size
) %
m_dma_memory_size
;
270
}
271
272
void
273
CardWrapper::read_current_address
()
274
{
275
m_card_mutex
.lock();
276
m_current_addr
=
m_flx_card
->m_bar0->DMA_DESC_STATUS[
m_dma_id
].current_address;
277
m_card_mutex
.unlock();
278
}
279
280
void
281
CardWrapper::process_DMA
()
282
{
283
TLOG_DEBUG
(
TLVL_WORK_STEPS
) <<
"CardWrapper starts processing blocks..."
;
284
while
(
m_run_marker
.load()) {
285
286
// First fix us poll until read address makes sense
287
while
((
m_current_addr
<
m_phys_addr
) || (
m_phys_addr
+
m_dma_memory_size
<
m_current_addr
)) {
288
if
(
m_run_marker
.load()) {
289
read_current_address
();
290
std::this_thread::sleep_for(std::chrono::microseconds(5000));
// fix 5ms initial poll
291
}
else
{
292
TLOG_DEBUG
(
TLVL_WORK_STEPS
) <<
"Stop issued during poll! Returning..."
;
293
return
;
294
}
295
}
296
297
// Loop or wait for interrupt while there are not enough data
298
while
(
bytes_available
() <
m_block_threshold
*
m_block_size
) {
299
if
(
m_run_marker
.load()) {
300
if
(
m_interrupt_mode
) {
301
m_card_mutex
.lock();
302
#if REGMAP_VERSION < 0x500
303
m_flx_card
->irq_wait(
IRQ_DATA_AVAILABLE
);
304
#else
305
m_flx_card
->irq_wait(
IRQ_DATA_AVAILABLE
+
m_dma_id
);
306
#endif
// REGMAP_VERSION
307
m_card_mutex
.unlock();
308
}
else
{
// poll mode
309
std::this_thread::sleep_for(std::chrono::microseconds(
m_poll_time
));
310
}
311
read_current_address
();
312
}
else
{
313
TLOG_DEBUG
(
TLVL_WORK_STEPS
) <<
"Stop issued during waiting for data! Returning..."
;
314
return
;
315
}
316
}
317
318
// Set write index and start DMA advancing
319
u_long write_index = (
m_current_addr
-
m_phys_addr
) /
m_block_size
;
320
uint64_t bytes = 0;
// NOLINT
321
while
(
m_read_index
!= write_index) {
322
uint64_t from_address =
m_virt_addr
+ (
m_read_index
*
m_block_size
);
// NOLINT
323
324
// Handle block address
325
if
(
m_block_addr_handler_available
) {
326
m_handle_block_addr
(from_address);
327
}
328
329
// Advance
330
m_read_index
= (
m_read_index
+ 1) % (
m_dma_memory_size
/
m_block_size
);
331
bytes +=
m_block_size
;
332
}
333
334
// here check if we can move the read pointer in the circular buffer
335
m_destination
=
m_phys_addr
+ (write_index *
m_block_size
) - (
m_margin_blocks
*
m_block_size
);
336
if
(
m_destination
<
m_phys_addr
) {
337
m_destination
+=
m_dma_memory_size
;
338
}
339
340
// Finally, set new pointer
341
m_card_mutex
.lock();
342
m_flx_card
->dma_set_ptr(
m_dma_id
,
m_destination
);
343
m_card_mutex
.unlock();
344
}
345
TLOG_DEBUG
(
TLVL_WORK_STEPS
) <<
"CardWrapper processor thread finished."
;
346
}
347
348
}
// namespace flxlibs
349
}
// namespace dunedaq
TLVL_BOOKKEEPING
@ TLVL_BOOKKEEPING
Definition
CardControllerWrapper.cpp:34
TLVL_WORK_STEPS
@ TLVL_WORK_STEPS
Definition
CardControllerWrapper.cpp:33
CardWrapper.hpp
FelixDefinitions.hpp
IRQ_DATA_AVAILABLE
#define IRQ_DATA_AVAILABLE
Definition
FelixDefinitions.hpp:22
FelixIssues.hpp
ERS_HERE
#define ERS_HERE
Definition
LocalContext.hpp:127
dunedaq::appmodel::FelixInterface
Definition
FelixInterface.hpp:27
dunedaq::appmodel::FelixInterface::get_dma_memory_size_gb
uint32_t get_dma_memory_size_gb() const
Get "dma_memory_size_gb" attribute value. CMEM_RCC memory to allocate in GBs.
Definition
FelixInterface.hpp:293
dunedaq::flxlibs::CardWrapper::read_current_address
void read_current_address()
Definition
CardWrapper.cpp:273
dunedaq::flxlibs::CardWrapper::stop_DMA
void stop_DMA()
Definition
CardWrapper.cpp:257
dunedaq::flxlibs::CardWrapper::m_phys_addr
uint64_t m_phys_addr
Definition
CardWrapper.hpp:101
dunedaq::flxlibs::CardWrapper::m_dma_processor
utilities::ReusableThread m_dma_processor
Definition
CardWrapper.hpp:109
dunedaq::flxlibs::CardWrapper::m_interrupt_mode
bool m_interrupt_mode
Definition
CardWrapper.hpp:86
dunedaq::flxlibs::CardWrapper::m_destination
u_long m_destination
Definition
CardWrapper.hpp:104
dunedaq::flxlibs::CardWrapper::m_dma_memory_size
std::size_t m_dma_memory_size
Definition
CardWrapper.hpp:98
dunedaq::flxlibs::CardWrapper::m_margin_blocks
size_t m_margin_blocks
Definition
CardWrapper.hpp:84
dunedaq::flxlibs::CardWrapper::process_DMA
void process_DMA()
Definition
CardWrapper.cpp:281
dunedaq::flxlibs::CardWrapper::m_dma_id
uint8_t m_dma_id
Definition
CardWrapper.hpp:83
dunedaq::flxlibs::CardWrapper::m_current_addr
uint64_t m_current_addr
Definition
CardWrapper.hpp:102
dunedaq::flxlibs::CardWrapper::set_running
void set_running(bool should_run)
Definition
CardWrapper.cpp:143
dunedaq::flxlibs::CardWrapper::m_handle_block_addr
std::function< void(uint64_t)> m_handle_block_addr
Definition
CardWrapper.hpp:110
dunedaq::flxlibs::CardWrapper::m_run_lock
std::atomic< bool > m_run_lock
Definition
CardWrapper.hpp:108
dunedaq::flxlibs::CardWrapper::m_block_size
static constexpr size_t m_block_size
Definition
CardWrapper.hpp:61
dunedaq::flxlibs::CardWrapper::m_flx_card
UniqueFlxCard m_flx_card
Definition
CardWrapper.hpp:94
dunedaq::flxlibs::CardWrapper::allocate_CMEM
int allocate_CMEM(uint8_t numa, u_long bsize, u_long *paddr, u_long *vaddr)
Definition
CardWrapper.cpp:187
dunedaq::flxlibs::CardWrapper::m_run_marker
std::atomic< bool > m_run_marker
Definition
CardWrapper.hpp:78
dunedaq::flxlibs::CardWrapper::m_block_addr_handler_available
bool m_block_addr_handler_available
Definition
CardWrapper.hpp:111
dunedaq::flxlibs::CardWrapper::m_read_index
unsigned m_read_index
Definition
CardWrapper.hpp:103
dunedaq::flxlibs::CardWrapper::m_numa_id
uint8_t m_numa_id
Definition
CardWrapper.hpp:88
dunedaq::flxlibs::CardWrapper::m_logical_unit
uint8_t m_logical_unit
Definition
CardWrapper.hpp:81
dunedaq::flxlibs::CardWrapper::init_DMA
void init_DMA()
Definition
CardWrapper.cpp:217
dunedaq::flxlibs::CardWrapper::m_poll_time
size_t m_poll_time
Definition
CardWrapper.hpp:87
dunedaq::flxlibs::CardWrapper::m_links_enabled
std::vector< unsigned int > m_links_enabled
Definition
CardWrapper.hpp:89
dunedaq::flxlibs::CardWrapper::m_info_str
std::string m_info_str
Definition
CardWrapper.hpp:90
dunedaq::flxlibs::CardWrapper::~CardWrapper
~CardWrapper()
Definition
CardWrapper.cpp:68
dunedaq::flxlibs::CardWrapper::configure
void configure()
Definition
CardWrapper.cpp:77
dunedaq::flxlibs::CardWrapper::m_configured
bool m_configured
Definition
CardWrapper.hpp:79
dunedaq::flxlibs::CardWrapper::close_card
void close_card()
Definition
CardWrapper.cpp:173
dunedaq::flxlibs::CardWrapper::m_block_threshold
size_t m_block_threshold
Definition
CardWrapper.hpp:85
dunedaq::flxlibs::CardWrapper::m_card_mutex
std::mutex m_card_mutex
Definition
CardWrapper.hpp:95
dunedaq::flxlibs::CardWrapper::bytes_available
uint64_t bytes_available()
Definition
CardWrapper.cpp:267
dunedaq::flxlibs::CardWrapper::graceful_stop
void graceful_stop()
Definition
CardWrapper.cpp:120
dunedaq::flxlibs::CardWrapper::stop
void stop()
Definition
CardWrapper.cpp:137
dunedaq::flxlibs::CardWrapper::m_dma_wraparound
static constexpr size_t m_dma_wraparound
Definition
CardWrapper.hpp:62
dunedaq::flxlibs::CardWrapper::CardWrapper
CardWrapper(const appmodel::FelixInterface *cfg, std::vector< unsigned int >)
CardWrapper Constructor.
Definition
CardWrapper.cpp:36
dunedaq::flxlibs::CardWrapper::m_card_id
uint8_t m_card_id
Definition
CardWrapper.hpp:80
dunedaq::flxlibs::CardWrapper::m_cmem_handle
int m_cmem_handle
Definition
CardWrapper.hpp:99
dunedaq::flxlibs::CardWrapper::start
void start()
Definition
CardWrapper.cpp:103
dunedaq::flxlibs::CardWrapper::start_DMA
void start_DMA()
Definition
CardWrapper.cpp:247
dunedaq::flxlibs::CardWrapper::m_virt_addr
uint64_t m_virt_addr
Definition
CardWrapper.hpp:100
dunedaq::flxlibs::CardWrapper::m_dma_processor_name
static const std::string m_dma_processor_name
Definition
CardWrapper.hpp:107
dunedaq::flxlibs::CardWrapper::m_card_id_str
std::string m_card_id_str
Definition
CardWrapper.hpp:82
dunedaq::flxlibs::CardWrapper::open_card
void open_card()
Definition
CardWrapper.cpp:150
dunedaq::utilities::ReusableThread::set_work
bool set_work(Function &&f, Args &&... args)
Definition
ReusableThread.hpp:53
dunedaq::utilities::ReusableThread::get_readiness
bool get_readiness() const
Definition
ReusableThread.hpp:49
dunedaq::utilities::ReusableThread::set_name
void set_name(const std::string &name, int tid)
Definition
ReusableThread.cpp:41
TLVL_ENTER_EXIT_METHODS
#define TLVL_ENTER_EXIT_METHODS
Definition
TimingIssues.hpp:22
Logging.hpp
TLOG_DEBUG
#define TLOG_DEBUG(lvl,...)
Definition
Logging.hpp:116
TLOG
#define TLOG(...)
Definition
macro.hpp:21
dunedaq::flxlibs
Definition
AvailableParserOperations.hpp:27
dunedaq
The DUNE-DAQ namespace.
Definition
cib_utilities.cpp:5
ers::fatal
void fatal(const Issue &issue)
Definition
ers.hpp:111
ers::error
void error(const Issue &issue)
Definition
ers.hpp:101
Generated on
for DUNE-DAQ by
1.18.0