LCOV - code coverage report
Current view: top level - appmodel/src - DaphneApplication.cpp (source / functions) Coverage Total Hit
Test: code.result Lines: 0.0 % 144 0
Test Date: 2026-03-29 15:29:34 Functions: 0.0 % 15 0

            Line data    Source code
       1              : /**
       2              :  * @file DaphneApplication.cpp
       3              :  *
       4              :  * Implementation of DaphneApplication's generate_modules dal method
       5              :  *
       6              :  * This is part of the DUNE DAQ Software Suite, copyright 2023.
       7              :  * Licensing/copyright details are in the COPYING file that you should have
       8              :  * received with this code.
       9              :  */
      10              : 
      11              : #include "conffwk/Configuration.hpp"
      12              : #include "oks/kernel.hpp"
      13              : #include "logging/Logging.hpp"
      14              : 
      15              : #include "confmodel/GeoId.hpp"
      16              : #include "confmodel/DetectorStream.hpp"
      17              : #include "confmodel/NetworkInterface.hpp"
      18              : 
      19              : #include "ConfigObjectFactory.hpp"
      20              : #include "appmodel/appmodelIssues.hpp"
      21              : #include "appmodel/FelixDataSender.hpp"
      22              : #include "appmodel/DaphneConf.hpp"
      23              : #include "appmodel/DaphneMapEntry.hpp"
      24              : #include "appmodel/DaphneV2BoardConf.hpp"
      25              : #include "appmodel/DaphneV2Channel.hpp"
      26              : #include "appmodel/DaphneV2AFE.hpp"
      27              : #include "appmodel/DaphneV2ADC.hpp"
      28              : #include "appmodel/DaphneV2PGA.hpp"
      29              : #include "appmodel/DaphneV2LNA.hpp"
      30              : #include "appmodel/DaphneV2ControllerModule.hpp"
      31              : #include "appmodel/DaphneV3ControllerModule.hpp"
      32              : #include "appmodel/DaphneApplication.hpp"
      33              : #include "appmodel/FelixDetectorToDaqConnection.hpp"
      34              : #include "appmodel/NetworkDetectorToDaqConnection.hpp"
      35              : #include "appmodel/NWDetDataSender.hpp"
      36              : #include "appmodel/NWDetDataReceiver.hpp"
      37              : #include "appmodel/HermesDataSender.hpp"
      38              : #include "appmodel/HermesModuleConf.hpp"
      39              : #include "appmodel/HermesModule.hpp"
      40              : #include "appmodel/IpbusAddressTable.hpp"
      41              : 
      42              : #include <string>
      43              : #include <vector>
      44              : #include <bitset>
      45              : #include <iostream>
      46              : #include <fmt/core.h>
      47              : #include <set>
      48              : #include <map>
      49              : 
      50              : namespace dunedaq::appmodel {
      51              :   
      52              : std::vector<const confmodel::Resource*>
      53            0 : DaphneApplication::contained_resources() const {
      54            0 :   return to_resources(get_detector_connections());
      55              : }
      56              : 
      57              : void
      58            0 : DaphneApplication::generate_modules(std::shared_ptr<appmodel::ConfigurationHelper> helper) const
      59              : {
      60            0 :   ConfigObjectFactory obj_fac(this);
      61              : 
      62            0 :   std::vector<const confmodel::DaqModule*> modules;
      63              : 
      64            0 :   auto daphne_conf = get_configuration();
      65              : 
      66            0 :   std::map<std::string, const DaphneV2BoardConf*> conf_map;
      67            0 :   auto confs = daphne_conf->get_boards();
      68            0 :   for ( const auto & c : confs ) {
      69            0 :     conf_map[c->get_key()] = c->get_conf();
      70              :   }
      71              : 
      72              :   //  these maps are all indexed on the board id {detector].{crate}.{slot}
      73            0 :   std::map<std::string, bool> v3_map;
      74            0 :   std::map<std::string, const confmodel::NetworkInterface*> interfaces;
      75            0 :   std::map<std::string, std::string> ctrl_hosts;
      76              : 
      77              :   // map from ctrl_host to senders
      78            0 :   std::map<std::string, std::vector<const appmodel::HermesDataSender*> > hermes_senders;
      79              :   
      80            0 :   for (auto d2d_conn : get_detector_connections()) {
      81              : 
      82              :     // A Resource can be disabled and still its application can be enabled because the application can have multile resources, so we need to check which resources are enabled
      83            0 :     if (helper->is_disabled(d2d_conn)) {
      84            0 :       TLOG_DEBUG(7) << "Ignoring disabled DetectorToDaqConnection " << d2d_conn->UID();
      85            0 :       continue;
      86            0 :     }
      87              : 
      88            0 :     TLOG_DEBUG(6) << "Processing DetectorToDaqConnection " << d2d_conn->UID();
      89              :     // get the readout groups and the interfaces and streams therein; 1 reaout group corresponds to 1 data reader module
      90              : 
      91              :     // Redundant? Schema forbids 0 connections
      92            0 :     if (d2d_conn->contained_resources().empty()) {
      93            0 :       throw(BadConf(ERS_HERE, "DetectorToDaqConnection does not contain senders or receivers"));
      94              :     }
      95              : 
      96            0 :     auto flx_conn = dynamic_cast<const appmodel::FelixDetectorToDaqConnection *>( d2d_conn );  // NOLINT(runtime/rtti) 
      97            0 :     auto net_conn = dynamic_cast<const appmodel::NetworkDetectorToDaqConnection *>( d2d_conn );  // NOLINT(runtime/rtti)
      98              : 
      99            0 :     if ( ! net_conn && ! flx_conn) {
     100            0 :       throw BadConf(ERS_HERE, d2d_conn->UID() + " is neither felix or eth connection");
     101              :     }
     102              : 
     103            0 :     if ( flx_conn ) {
     104            0 :       auto det_senders = flx_conn->get_felix_senders();
     105              : 
     106              :       // Loop over senders
     107            0 :       for (const auto* felix_sender : det_senders) {
     108              :         
     109            0 :         if ( helper->is_disabled(felix_sender) ) {
     110            0 :           TLOG() << "Skipping disabled sender: " << felix_sender->UID();
     111            0 :           continue;
     112            0 :         }
     113              :         
     114            0 :         auto ip = felix_sender -> get_control_host();
     115              :         
     116              :         // from the felix sender we get the DetStream and then the GeoID
     117              :         
     118            0 :         auto streams = felix_sender -> get_streams();
     119              :         
     120            0 :         for ( const auto * det_s : streams ) {
     121              :           
     122            0 :           if ( helper->is_disabled(det_s) ) {
     123            0 :             TLOG() << "Skipping disabled DetStream: " << det_s->UID();
     124            0 :             continue;
     125            0 :           }
     126              : 
     127            0 :           auto geo_id = det_s->get_geo_id();
     128            0 :           auto id = fmt::format("{}.{}.{}", geo_id->get_detector_id(), geo_id->get_crate_id(), geo_id->get_slot_id());
     129            0 :           if (!v3_map.contains(id)) {
     130            0 :             v3_map[id] = false;
     131              :           } 
     132              :           
     133            0 :         } // loop over DetStreams
     134              :         
     135            0 :       } // loop over det_senders
     136            0 :     } // if flx connection
     137              : 
     138            0 :     if ( net_conn ) {
     139            0 :       auto det_senders = net_conn->get_net_senders();
     140              : 
     141            0 :       for ( const auto* nw_sender : det_senders ) {
     142            0 :         if ( helper->is_disabled(nw_sender) ) {
     143            0 :           TLOG() << "Skipping disabled sender: " << nw_sender->UID();
     144            0 :           continue;
     145            0 :         }
     146              : 
     147              :         // Check the sender type, must me a HermesSender
     148            0 :         const auto* hrms_sender = nw_sender->cast<appmodel::HermesDataSender>();
     149            0 :         if (!hrms_sender ) {
     150            0 :           throw(BadConf(ERS_HERE, fmt::format("DataSender {} is not a appmodel::HermesDataSender", nw_sender->UID())));
     151              :         }
     152              : 
     153            0 :         hermes_senders[hrms_sender->get_control_host()].push_back(hrms_sender);
     154              :           
     155            0 :         auto streams = nw_sender -> get_streams();
     156            0 :         for ( const auto * det_s : streams ) {
     157              :           
     158            0 :           if ( helper->is_disabled(det_s) ) {
     159            0 :             TLOG() << "Skipping disabled DetStream: " << det_s->UID();
     160            0 :             continue;
     161            0 :           }
     162              :           
     163            0 :           auto geo_id = det_s->get_geo_id();
     164            0 :           auto id = fmt::format("{}.{}.{}", geo_id->get_detector_id(), geo_id->get_crate_id(), geo_id->get_slot_id());
     165            0 :           if (!v3_map.contains(id)) {
     166            0 :             v3_map[id] = true;
     167            0 :             interfaces[id] = net_conn->get_net_receiver()->get_uses();
     168            0 :             ctrl_hosts[id] = hrms_sender->get_control_host();
     169              :           } 
     170              :           
     171            0 :         } // loop over streams
     172              : 
     173            0 :       } // loop over NW senders
     174              :       
     175            0 :     } // if net_connection
     176              : 
     177              :   } // loop over det2DAQ Connections
     178              : 
     179              : 
     180              :   
     181              :   
     182            0 :   for ( const auto & [id, v3] : v3_map ) {
     183              :   
     184            0 :     auto conf_it = conf_map.find(id);
     185            0 :     if ( conf_it == conf_map.end() ) {
     186            0 :       throw MissingDaphne(ERS_HERE, id);
     187              :     }
     188            0 :     auto conf = conf_it->second;
     189              : 
     190            0 :     conffwk::ConfigObject module_obj = obj_fac.create( (v3 ?  "DaphneV3ControllerModule" : "DaphneV2ControllerModule"), fmt::format("controller-{}", id) );
     191            0 :     module_obj.set_obj("daphne_conf", & daphne_conf -> config_object() );
     192            0 :     module_obj.set_obj("board_conf", & conf -> config_object() );
     193              : 
     194            0 :     auto module = obj_fac.get_dal<confmodel::DaqModule>(module_obj); 
     195            0 :     modules.push_back(module);
     196              : 
     197              : 
     198              :     // Create Hermes Modules
     199            0 :     if (v3) {
     200            0 :       std::string hermes_uid = fmt::format("daphne-hermes-ctrl-{}", id);
     201            0 :       conffwk::ConfigObject hermes_obj = obj_fac.create("HermesModule", hermes_uid);
     202            0 :       hermes_obj.set_obj("address_table", &this->get_hermes_module_conf()->get_address_table()->config_object());
     203            0 :       hermes_obj.set_by_val<std::string>("uri", fmt::format("{}://{}:{}", this->get_hermes_module_conf()->get_ipbus_type(), ctrl_hosts[id], this->get_hermes_module_conf()->get_ipbus_port()));
     204            0 :       hermes_obj.set_by_val<uint32_t>("timeout_ms", this->get_hermes_module_conf()->get_ipbus_timeout_ms());  // NOLINT
     205            0 :       hermes_obj.set_obj("destination", & interfaces[id]->config_object());
     206              :       
     207            0 :       std::vector< const conffwk::ConfigObject * > links_obj;
     208            0 :       const auto & senders = hermes_senders[ctrl_hosts[id]];
     209            0 :       for ( const auto* sndr : senders ){
     210            0 :         links_obj.push_back(&sndr->config_object());
     211              :       }
     212            0 :       hermes_obj.set_objs("links", links_obj);
     213              :       
     214            0 :       modules.push_back(obj_fac.get_dal<appmodel::HermesModule>(hermes_obj));
     215              : 
     216            0 :     }
     217              :     
     218            0 :   } // ips
     219              : 
     220            0 :   obj_fac.update_modules(modules);
     221            0 : }  // NOLINT 
     222              : 
     223              : 
     224              : bool
     225            0 : DaphneV2BoardConf::is_channel_used(size_t ch) const {
     226              : 
     227            0 :   for ( auto ch_p : get_active_channels() ) {
     228            0 :     if ( ch_p->get_channel_id() == ch ) {
     229            0 :       return true;
     230              :     }
     231              :   }
     232              : 
     233            0 :   return false;
     234              : }
     235              : 
     236              : const DaphneV2Channel &
     237            0 : DaphneV2BoardConf::get_channel(size_t ch) const {
     238              : 
     239            0 :   for ( auto ch_p : get_active_channels() ) {
     240            0 :     if ( ch_p->get_channel_id() == ch ) {
     241            0 :       return *ch_p;
     242              :     }
     243              :   }
     244              :   
     245            0 :   return *get_default_channel();
     246              : }
     247              : 
     248              : bool
     249            0 : DaphneV2BoardConf::is_afe_used(size_t afe) const {
     250              : 
     251            0 :   auto begin = afe*8;
     252            0 :   auto end   = (afe+1)*8;
     253            0 :   for ( size_t i = begin; i < end; ++i) {
     254            0 :     if( is_channel_used(i) ) return true;
     255              :   }
     256              : 
     257              :   return false;
     258              : }
     259              : 
     260              : const DaphneV2AFE &
     261            0 : DaphneV2BoardConf::get_afe(size_t ch) const {
     262              : 
     263            0 :   if ( ! is_afe_used(ch) ) return *get_default_afe();
     264              :   
     265            0 :   for ( auto afe_p : get_active_afes() ) {
     266            0 :     if ( afe_p->get_afe_id() == ch ) {
     267            0 :       return *afe_p;
     268              :     }
     269              :   }
     270              : 
     271            0 :   throw appmodel::MissingAFE(ERS_HERE, UID(), ch);
     272              : }
     273              : 
     274              : 
     275              : uint16_t
     276            0 : DaphneV2ADC::get_reg4() const {
     277              : 
     278              :   // ADC, reg 4 has no parsing as it's all made of booleans                                                     
     279            0 :   std::bitset<5> reg4;                                                                                          
     280              :   // bits 0 and 2 are reserved                                                                                  
     281            0 :   reg4[1] = get_low_resolution();
     282            0 :   reg4[3] = get_output_offset_binary();
     283            0 :   reg4[4] = get_MSB_first();
     284            0 :   return reg4.to_ulong(); 
     285              : }
     286              : 
     287              : uint16_t
     288            0 : DaphneV2PGA::get_reg51() const {
     289              : 
     290            0 :   std::bitset<14> reg51(get_lpf_cut_frequency());
     291            0 :   reg51 <<= 1;                                                                                                  
     292            0 :   reg51[4] = get_integrator_disable();
     293            0 :   reg51[7] = true;  // clamp is always disabled and we are in low noise mode
     294            0 :   reg51[13] = get_gain();
     295              : 
     296            0 :   return reg51.to_ulong() ;                  
     297              : }
     298              : 
     299              : uint16_t
     300            0 : DaphneV2LNA::get_reg52() const {
     301              : 
     302            0 :   std::bitset<16> reg52;                                                                                        
     303              : 
     304            0 :   decltype(reg52) clamp(get_clamp());
     305            0 :   clamp <<= 6;
     306              : 
     307            0 :   reg52[12] = get_integrator_disable();
     308              :   
     309            0 :   decltype(reg52) gain(get_gain());
     310            0 :   clamp <<= 13;
     311              : 
     312            0 :   reg52 |= clamp;
     313            0 :   reg52 |= gain;
     314              : 
     315            0 :   return reg52.to_ulong();
     316              : }
     317              :  
     318              : } // namespace dunedaq::appmodel
        

Generated by: LCOV version 2.0-1