LCOV - code coverage report
Current view: top level - flxlibs/plugins - FelixReaderModule.cpp (source / functions) Coverage Total Hit
Test: code.result Lines: 0.0 % 97 0
Test Date: 2026-03-29 15:29:34 Functions: 0.0 % 14 0

            Line data    Source code
       1              : /**
       2              :  * @file FelixReaderModule.cc FelixReaderModule DAQModule implementation
       3              :  *
       4              :  * This is part of the DUNE DAQ Application Framework, copyright 2020.
       5              :  * Licensing/copyright details are in the COPYING file that you should have
       6              :  * received with this code.
       7              :  */
       8              : #include "confmodel/Connection.hpp"
       9              : #include "confmodel/QueueWithSourceId.hpp"
      10              : #include "confmodel/DetDataSender.hpp"
      11              : #include "confmodel/DetectorStream.hpp"
      12              : #include "confmodel/GeoId.hpp"
      13              : 
      14              : #include "appmodel/DataMoveCallbackConf.hpp"
      15              : #include "appmodel/DataReaderModule.hpp"
      16              : #include "appmodel/FelixDetectorToDaqConnection.hpp"
      17              : #include "appmodel/FelixInterface.hpp"
      18              : #include "appmodel/FelixDataSender.hpp"
      19              : 
      20              : #include "CreateElink.hpp"
      21              : #include "FelixReaderModule.hpp"
      22              : #include "FelixIssues.hpp"
      23              : 
      24              : #include "logging/Logging.hpp"
      25              : 
      26              : #include "flxcard/FlxException.h"
      27              : 
      28              : #include <chrono>
      29              : #include <memory>
      30              : #include <string>
      31              : #include <thread>
      32              : #include <utility>
      33              : #include <vector>
      34              : 
      35              : /**
      36              :  * @brief Name used by TRACE TLOG calls from this source file
      37              :  */
      38              : #define TRACE_NAME "FelixReaderModule" // NOLINT
      39              : 
      40              : /**
      41              :  * @brief TRACE debug levels used in this source file
      42              :  */
      43              : enum
      44              : {
      45              :   TLVL_ENTER_EXIT_METHODS = 5,
      46              :   TLVL_WORK_STEPS = 10,
      47              :   TLVL_BOOKKEEPING = 15
      48              : };
      49              : 
      50              : namespace dunedaq {
      51              : namespace flxlibs {
      52              : 
      53            0 : FelixReaderModule::FelixReaderModule(const std::string& name)
      54              :   : DAQModule(name)
      55            0 :   , m_configured(false)
      56            0 :   , m_card_id(0)
      57            0 :   , m_logical_unit(0)
      58            0 :   , m_links_enabled()
      59            0 :   , m_num_links(0)
      60            0 :   , m_block_size(0)
      61            0 :   , m_block_router(nullptr)
      62              : //, block_ptr_sinks_{ }
      63              : 
      64              : {
      65              :  
      66            0 :   register_command("conf", &FelixReaderModule::do_configure);
      67            0 :   register_command("start", &FelixReaderModule::do_start);
      68            0 :   register_command("stop_trigger_sources", &FelixReaderModule::do_stop);
      69            0 : }
      70              : 
      71              : void
      72            0 : FelixReaderModule::init(const std::shared_ptr<appfwk::ConfigurationManager> mcfg)
      73              : {
      74              :   //auto ini = args.get<appfwk::app::ModInit>();
      75              :   
      76            0 :   auto modconf = mcfg->get_dal<appmodel::DataReaderModule>(get_name());
      77            0 :   auto session = mcfg->get_session();
      78              : 
      79            0 :   if (modconf->get_connections().size() != 1) {
      80            0 :     throw InitializationError(ERS_HERE, "FLX Data Reader does not have a unique associated flx_if");
      81              :   }
      82              : 
      83            0 :   const auto  det_conn = modconf->get_connections()[0]->cast<appmodel::FelixDetectorToDaqConnection>();
      84              : 
      85              : // Create a source_id to local elink map
      86            0 :   std::map<uint, uint> src_id_to_elink_map;
      87            0 :   auto flx_if = det_conn->receiver()->cast<appmodel::FelixInterface>();
      88            0 :   auto det_senders = det_conn->get_felix_senders();
      89              : 
      90            0 :   if (!det_senders.empty()) { // Redundant test as schema forbids 0 senders
      91            0 :     for (const auto& data_sender : det_senders) {
      92              :       // Check if sender enabled
      93            0 :       if (data_sender->is_disabled(*session)) {
      94            0 :         continue;
      95              :       }
      96            0 :       for (const auto& stream : data_sender->get_streams()) {
      97            0 :         src_id_to_elink_map[stream->get_source_id()] = data_sender->get_link();
      98              :       }
      99              : 
     100            0 :       TLOG(TLVL_BOOKKEEPING) << "Registering link: " << (uint32_t)data_sender->get_link() << " / " << m_links_enabled.size();
     101            0 :       m_links_enabled.push_back(data_sender->get_link());
     102              : 
     103              :     }
     104              :   }
     105            0 :   m_num_links = m_links_enabled.size();
     106            0 :   if (flx_if != nullptr) {
     107            0 :         m_card_wrapper = std::make_unique<CardWrapper>(flx_if, m_links_enabled);
     108            0 :         m_card_id = flx_if->get_card();
     109            0 :         m_logical_unit = flx_if->get_slr();
     110            0 :         m_block_size = flx_if->get_dma_block_size() * m_1kb_block_size;
     111            0 :         m_chunk_trailer_size = flx_if->get_chunk_trailer_size();
     112              :   }
     113              : 
     114            0 :   for (auto cb :modconf->get_raw_data_callbacks()) {
     115            0 :     auto cb_with_id = cb->cast<appmodel::DataMoveCallbackConf>();
     116            0 :     if (cb_with_id == nullptr) continue;
     117            0 :     TLOG_DEBUG(TLVL_WORK_STEPS) << ": CardReader output callback is " << cb_with_id->UID();
     118            0 :     TLOG_DEBUG(TLVL_WORK_STEPS) << "Creating ElinkModel for target callback: " << cb_with_id->UID() << " DLH number: " << cb_with_id->get_source_id();
     119            0 :     auto elink = src_id_to_elink_map[cb_with_id->get_source_id()];
     120            0 :     auto link_ptr = m_elinks[elink] = createElinkModel(cb_with_id);
     121            0 :     if ( ! link_ptr ) {
     122            0 :       ers::fatal(InitializationError(ERS_HERE, "CreateElink failed to provide an appropriate model for queue!"));
     123              :     }
     124            0 :     register_node( cb_with_id->UID(), link_ptr);
     125            0 :     link_ptr->init(m_block_queue_capacity);
     126            0 :   }
     127              : 
     128              :   // Router function of block to appropriate ElinkHandlers
     129            0 :   m_block_router = [&](uint64_t block_addr) { // NOLINT
     130              :     // block_counter++;
     131            0 :     const auto* block = const_cast<felix::packetformat::block*>(
     132            0 :       felix::packetformat::block_from_bytes(reinterpret_cast<const char*>(block_addr)) // NOLINT
     133              :     );
     134            0 :     auto elink = block->elink;
     135            0 :     if (m_elinks.count(elink) != 0) {
     136            0 :       m_elinks[elink]->queue_in_block_address(block_addr);
     137              :     } else {
     138              :       // Really bad -> unexpeced ELINK ID in Block.
     139              :       // This check is needed in order to avoid dynamically add thousands
     140              :       // of ELink parser implementations on the fly, in case the data
     141              :       // corruption is extremely severe.
     142              :       //
     143              :       // Possible causes:
     144              :       //   -> enabled links that don't connect to anything
     145              :       //   -> unexpected format (fw/sw version missmatch)
     146              :       //   -> data corruption from FE
     147              :       //   -> data corruption from CR (really rare, last possible cause)
     148              : 
     149              :       // NO TLOG_DEBUG, but should count and periodically report corrupted DMA blocks.
     150              :     }
     151            0 :   };
     152              : 
     153              :   // Set function for the CardWrapper's block processor.
     154            0 :   m_card_wrapper->set_block_addr_handler(m_block_router);
     155            0 : }
     156              : 
     157              : void
     158            0 : FelixReaderModule::do_configure(const CommandData_t& /*args*/)
     159              : {
     160              :    
     161            0 :     bool is_32b_trailer = false;
     162              : 
     163            0 :     TLOG(TLVL_BOOKKEEPING) << "Number of felix links specified in configuration: " << m_links_enabled.size();
     164            0 :     TLOG(TLVL_BOOKKEEPING) << "Number of data link handlers: " << m_elinks.size();
     165              : 
     166              :     // Config checks
     167            0 :     if (m_num_links != m_elinks.size()) {
     168            0 :       ers::fatal(ElinkConfigurationInconsistency(ERS_HERE, m_links_enabled.size()));
     169              :     }
     170            0 :     if (m_block_size % m_1kb_block_size != 0) {
     171            0 :       ers::fatal(BlockSizeConfigurationInconsistency(ERS_HERE, m_block_size));
     172            0 :     } else if (m_block_size != m_1kb_block_size && m_chunk_trailer_size != m_32b_trailer_size) {
     173            0 :       ers::fatal(BlockSizeConfigurationInconsistency(ERS_HERE, m_block_size));
     174            0 :     } else if (m_chunk_trailer_size == m_32b_trailer_size) {
     175            0 :       is_32b_trailer = true;
     176              :     }
     177              : 
     178              :     // Configure components
     179            0 :     TLOG(TLVL_WORK_STEPS) << "Card ID: " << m_card_id;
     180            0 :     TLOG(TLVL_WORK_STEPS) << "Configuring components with Block size:" << m_block_size
     181            0 :                           << " & trailer size: " << m_chunk_trailer_size;
     182            0 :     m_card_wrapper->configure();
     183              :     // get linkids defined by queues
     184            0 :     std::vector<int> linkids;
     185            0 :     for(auto& [id, elink] : m_elinks) {
     186            0 :       linkids.push_back(id);
     187              :     }
     188              :     // loop through all elinkmodels, change the linkids to link tags and configure
     189            0 :     for (unsigned i = 0; i < m_num_links; ++i) {
     190            0 :       auto elink = m_elinks.extract(linkids[i]);
     191            0 :       auto tag = m_links_enabled[i] * m_elink_multiplier;
     192            0 :       elink.key() = tag;
     193            0 :       m_elinks.insert(std::move(elink));
     194            0 :       m_elinks[tag]->set_ids(m_card_id, m_logical_unit, m_links_enabled[i], tag);
     195            0 :       m_elinks[tag]->conf(m_block_size, is_32b_trailer);
     196            0 :     }
     197            0 : }
     198              : 
     199              : void
     200            0 : FelixReaderModule::do_start(const CommandData_t& /*args*/)
     201              : {
     202            0 :     m_card_wrapper->start();
     203            0 :     for (auto& [tag, elink] : m_elinks) {
     204            0 :       elink->acquire_callback();
     205            0 :       elink->start();
     206              :     }
     207            0 : }
     208              : 
     209              : void
     210            0 : FelixReaderModule::do_stop(const CommandData_t& /*args*/)
     211              : {
     212            0 :     m_card_wrapper->stop();
     213            0 :     for (auto& [tag, elink] : m_elinks) {
     214            0 :       elink->stop();
     215              :     }
     216            0 : }
     217              : 
     218              : 
     219              : } // namespace flxlibs
     220              : } // namespace dunedaq
     221              : 
     222            0 : DEFINE_DUNE_DAQ_MODULE(dunedaq::flxlibs::FelixReaderModule)
        

Generated by: LCOV version 2.0-1