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

Generated by: LCOV version 2.0-1