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
77
void
78
CardWrapper::configure
()
79
{
80
if
(
m_configured
) {
81
TLOG_DEBUG
(
TLVL_ENTER_EXIT_METHODS
) <<
"Card is already configured! Won't touch it."
;
82
}
else
{
83
TLOG_DEBUG
(
TLVL_WORK_STEPS
) <<
"Configuring CardWrapper of card "
<<
m_card_id_str
;
84
// Open card
85
open_card
();
86
TLOG_DEBUG
(
TLVL_WORK_STEPS
) <<
"Card["
<<
m_card_id_str
<<
"] opened."
;
87
// Allocate CMEM
88
m_cmem_handle
=
allocate_CMEM
(
m_numa_id
,
m_dma_memory_size
, &
m_phys_addr
, &
m_virt_addr
);
89
TLOG_DEBUG
(
TLVL_WORK_STEPS
) <<
"Card["
<<
m_card_id_str
<<
"] CMEM memory allocated with "
90
<< std::to_string(
m_dma_memory_size
) <<
" Bytes."
;
91
// Stop currently running DMA
92
stop_DMA
();
93
TLOG_DEBUG
(
TLVL_WORK_STEPS
) <<
"Card["
<<
m_card_id_str
<<
"] DMA interactions force stopped."
;
94
// Init DMA between software and card
95
init_DMA
();
96
TLOG_DEBUG
(
TLVL_WORK_STEPS
) <<
"Card["
<<
m_card_id_str
<<
"] DMA access initialized."
;
97
// The rest was some CPU pinning.
98
TLOG_DEBUG
(
TLVL_WORK_STEPS
) <<
m_card_id_str
<<
"] is configured for datataking."
;
99
m_configured
=
true
;
100
}
101
}
102
103
void
104
CardWrapper::start
()
105
{
106
TLOG_DEBUG
(
TLVL_ENTER_EXIT_METHODS
) <<
"Starting CardWrapper of card "
<<
m_card_id_str
<<
"..."
;
107
if
(!
m_run_marker
.load()) {
108
if
(!
m_block_addr_handler_available
) {
109
TLOG
() <<
"Block Address handler is not set! Is it intentional?"
;
110
}
111
start_DMA
();
112
set_running
(
true
);
113
m_dma_processor
.set_work(&
CardWrapper::process_DMA
,
this
);
114
TLOG
() <<
"Started CardWrapper of card "
<<
m_card_id_str
<<
"..."
;
115
}
else
{
116
TLOG
() <<
"CardWrapper of card "
<<
m_card_id_str
<<
" is already running!"
;
117
}
118
}
119
120
void
121
CardWrapper::graceful_stop
()
122
{
123
TLOG_DEBUG
(
TLVL_ENTER_EXIT_METHODS
) <<
"Stopping CardWrapper of card "
<<
m_card_id_str
<<
"..."
;
124
if
(
m_run_marker
.load()) {
125
set_running
(
false
);
126
while
(!
m_dma_processor
.get_readiness()) {
127
std::this_thread::sleep_for(std::chrono::milliseconds(10));
128
}
129
stop_DMA
();
130
init_DMA
();
131
TLOG
() <<
"Stopped CardWrapper of card "
<<
m_card_id_str
<<
"!"
;
132
}
else
{
133
TLOG
() <<
"CardWrapper of card "
<<
m_card_id_str
<<
" is already stopped!"
;
134
}
135
}
136
137
void
138
CardWrapper::stop
()
139
{
140
graceful_stop
();
141
}
142
143
void
144
CardWrapper::set_running
(
bool
should_run)
145
{
146
bool
was_running =
m_run_marker
.exchange(should_run);
147
TLOG_DEBUG
(
TLVL_WORK_STEPS
) <<
"Active state was toggled from "
<< was_running <<
" to "
<< should_run;
148
}
149
150
void
151
CardWrapper::open_card
()
152
{
153
TLOG_DEBUG
(
TLVL_WORK_STEPS
) <<
"Opening FELIX card (with DMA lock mask)"
<<
m_card_id_str
;
154
try
{
155
m_card_mutex
.lock();
156
auto
absolute_card_id =
m_card_id
+
m_logical_unit
;
157
u_int current_lock_mask =
m_flx_card
->get_lock_mask(absolute_card_id);
158
TLOG_DEBUG
(
TLVL_WORK_STEPS
) <<
"Current lock mask for FELIX card "
<<
m_card_id_str
<<
" 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
CardWrapper.hpp
FelixDefinitions.hpp
IRQ_DATA_AVAILABLE
#define IRQ_DATA_AVAILABLE
Definition
FelixDefinitions.hpp:22
FelixIssues.hpp
TLVL_BOOKKEEPING
@ TLVL_BOOKKEEPING
Definition
IfaceWrapper.cpp:53
TLVL_WORK_STEPS
@ TLVL_WORK_STEPS
Definition
IfaceWrapper.cpp:52
ERS_HERE
#define ERS_HERE
Definition
LocalContext.hpp:141
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:102
dunedaq::flxlibs::CardWrapper::m_dma_processor
utilities::ReusableThread m_dma_processor
Definition
CardWrapper.hpp:110
dunedaq::flxlibs::CardWrapper::m_interrupt_mode
bool m_interrupt_mode
Definition
CardWrapper.hpp:87
dunedaq::flxlibs::CardWrapper::m_destination
u_long m_destination
Definition
CardWrapper.hpp:105
dunedaq::flxlibs::CardWrapper::m_dma_memory_size
std::size_t m_dma_memory_size
Definition
CardWrapper.hpp:99
dunedaq::flxlibs::CardWrapper::m_margin_blocks
size_t m_margin_blocks
Definition
CardWrapper.hpp:85
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:84
dunedaq::flxlibs::CardWrapper::m_current_addr
uint64_t m_current_addr
Definition
CardWrapper.hpp:103
dunedaq::flxlibs::CardWrapper::set_running
void set_running(bool should_run)
Definition
CardWrapper.cpp:144
dunedaq::flxlibs::CardWrapper::m_handle_block_addr
std::function< void(uint64_t)> m_handle_block_addr
Definition
CardWrapper.hpp:111
dunedaq::flxlibs::CardWrapper::m_run_lock
std::atomic< bool > m_run_lock
Definition
CardWrapper.hpp:109
dunedaq::flxlibs::CardWrapper::m_block_size
static constexpr size_t m_block_size
Definition
CardWrapper.hpp:62
dunedaq::flxlibs::CardWrapper::m_flx_card
UniqueFlxCard m_flx_card
Definition
CardWrapper.hpp:95
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:79
dunedaq::flxlibs::CardWrapper::m_block_addr_handler_available
bool m_block_addr_handler_available
Definition
CardWrapper.hpp:112
dunedaq::flxlibs::CardWrapper::m_read_index
unsigned m_read_index
Definition
CardWrapper.hpp:104
dunedaq::flxlibs::CardWrapper::m_numa_id
uint8_t m_numa_id
Definition
CardWrapper.hpp:89
dunedaq::flxlibs::CardWrapper::m_logical_unit
uint8_t m_logical_unit
Definition
CardWrapper.hpp:82
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:88
dunedaq::flxlibs::CardWrapper::m_links_enabled
std::vector< unsigned int > m_links_enabled
Definition
CardWrapper.hpp:90
dunedaq::flxlibs::CardWrapper::m_info_str
std::string m_info_str
Definition
CardWrapper.hpp:91
dunedaq::flxlibs::CardWrapper::~CardWrapper
~CardWrapper()
Definition
CardWrapper.cpp:68
dunedaq::flxlibs::CardWrapper::configure
void configure()
Definition
CardWrapper.cpp:78
dunedaq::flxlibs::CardWrapper::m_configured
bool m_configured
Definition
CardWrapper.hpp:80
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:86
dunedaq::flxlibs::CardWrapper::m_card_mutex
std::mutex m_card_mutex
Definition
CardWrapper.hpp:96
dunedaq::flxlibs::CardWrapper::bytes_available
uint64_t bytes_available()
Definition
CardWrapper.cpp:267
dunedaq::flxlibs::CardWrapper::graceful_stop
void graceful_stop()
Definition
CardWrapper.cpp:121
dunedaq::flxlibs::CardWrapper::stop
void stop()
Definition
CardWrapper.cpp:138
dunedaq::flxlibs::CardWrapper::m_dma_wraparound
static constexpr size_t m_dma_wraparound
Definition
CardWrapper.hpp:63
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:81
dunedaq::flxlibs::CardWrapper::m_cmem_handle
int m_cmem_handle
Definition
CardWrapper.hpp:100
dunedaq::flxlibs::CardWrapper::start
void start()
Definition
CardWrapper.cpp:104
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:101
dunedaq::flxlibs::CardWrapper::m_dma_processor_name
static const std::string m_dma_processor_name
Definition
CardWrapper.hpp:108
dunedaq::flxlibs::CardWrapper::m_card_id_str
std::string m_card_id_str
Definition
CardWrapper.hpp:83
dunedaq::flxlibs::CardWrapper::open_card
void open_card()
Definition
CardWrapper.cpp:151
Logging.hpp
TLOG_DEBUG
#define TLOG_DEBUG(lvl,...)
Definition
Logging.hpp:112
TLOG
#define TLOG(...)
Definition
macro.hpp:22
dunedaq::flxlibs
Definition
AvailableParserOperations.hpp:27
dunedaq
Including Qt Headers.
Definition
module.cpp:16
ers::fatal
void fatal(const Issue &issue)
Definition
ers.hpp:99
ers::error
void error(const Issue &issue)
Definition
ers.hpp:92
TLVL_ENTER_EXIT_METHODS
#define TLVL_ENTER_EXIT_METHODS
Definition
Issues.hpp:24
Generated on
for DUNE-DAQ by
1.17.0