DUNE-DAQ
DUNE Trigger and Data Acquisition software
Loading...
Searching...
No Matches
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
26enum
27{
29 TLVL_WORK_STEPS = 10,
30 TLVL_BOOKKEEPING = 15
31};
32
33namespace dunedaq {
34namespace flxlibs {
35
36CardWrapper::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
69{
70 TLOG_DEBUG(TLVL_ENTER_EXIT_METHODS) << "CardWrapper destructor called. First stop check, then closing card.";
72 close_card();
73 TLOG_DEBUG(TLVL_ENTER_EXIT_METHODS) << "CardWrapper destroyed.";
74}
75
76
77void
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
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
103void
105{
106 TLOG_DEBUG(TLVL_ENTER_EXIT_METHODS) << "Starting CardWrapper of card " << m_card_id_str << "...";
107 if (!m_run_marker.load()) {
109 TLOG() << "Block Address handler is not set! Is it intentional?";
110 }
111 start_DMA();
112 set_running(true);
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
120void
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
137void
142
143void
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
150void
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
172void
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
186int
187CardWrapper::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();
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
216void
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
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();
242 m_read_index = 0;
243 TLOG_DEBUG(TLVL_WORK_STEPS) << "flxCard initDMA done card[" << m_card_id_str << "]";
244}
245
246void
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();
253 m_card_mutex.unlock();
254}
255
256void
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
266inline uint64_t // NOLINT
271
272void
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
280void
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
288 if (m_run_marker.load()) {
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
299 if (m_run_marker.load()) {
300 if (m_interrupt_mode) {
301 m_card_mutex.lock();
302#if REGMAP_VERSION < 0x500
304#else
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 }
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
326 m_handle_block_addr(from_address);
327 }
328
329 // Advance
331 bytes += m_block_size;
332 }
333
334 // here check if we can move the read pointer in the circular buffer
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_ENTER_EXIT_METHODS
#define IRQ_DATA_AVAILABLE
#define ERS_HERE
uint32_t get_dma_memory_size_gb() const
Get "dma_memory_size_gb" attribute value. CMEM_RCC memory to allocate in GBs.
utilities::ReusableThread m_dma_processor
void set_running(bool should_run)
std::function< void(uint64_t)> m_handle_block_addr
static constexpr size_t m_block_size
int allocate_CMEM(uint8_t numa, u_long bsize, u_long *paddr, u_long *vaddr)
std::atomic< bool > m_run_marker
static constexpr size_t m_dma_wraparound
CardWrapper(const appmodel::FelixInterface *cfg, std::vector< unsigned int >)
CardWrapper Constructor.
static const std::string m_dma_processor_name
bool set_work(Function &&f, Args &&... args)
void set_name(const std::string &name, int tid)
#define TLVL_ENTER_EXIT_METHODS
#define TLOG_DEBUG(lvl,...)
Definition Logging.hpp:112
#define TLOG(...)
Definition macro.hpp:22
Including Qt Headers.
void fatal(const Issue &issue)
Definition ers.hpp:88
void error(const Issue &issue)
Definition ers.hpp:81