LCOV - code coverage report
Current view: top level - hermesmodules/src - HermesCoreController.cpp (source / functions) Coverage Total Hit
Test: code.result Lines: 0.0 % 186 0
Test Date: 2025-12-21 13:07:08 Functions: 0.0 % 14 0

            Line data    Source code
       1              : #include "hermesmodules/HermesCoreController.hpp"
       2              : 
       3              : #include <chrono>         // std::chrono::seconds
       4              : #include <thread>         // std::this_thread::sleep_for
       5              : #include <fmt/core.h>
       6              : 
       7              : namespace dunedaq {
       8              : namespace hermesmodules {
       9              : 
      10              : //-----------------------------------------------------------------------------
      11            0 : HermesCoreController::HermesCoreController(uhal::HwInterface hw, std::string readout_id) :
      12            0 :   m_hw(hw), m_readout(m_hw.getNode(readout_id)) {
      13              : 
      14            0 :     this->load_hw_info();
      15              : 
      16            0 : }
      17              : 
      18              : //-----------------------------------------------------------------------------
      19            0 : HermesCoreController::~HermesCoreController() {
      20              : 
      21            0 : }
      22              : 
      23              : //-----------------------------------------------------------------------------
      24              : void
      25            0 : HermesCoreController::load_hw_info() {
      26              : 
      27              :   // Check magic number
      28            0 :   auto magic = m_readout.getNode("info.magic").read();
      29            0 :   m_readout.getClient().dispatch();
      30            0 :   if (magic.value() != 0xdeadbeef){
      31              :       // TODO: add ERS exception
      32            0 :       throw MagicNumberError(ERS_HERE, magic.value(),0xdeadbeef);
      33              :   }
      34              : 
      35              : 
      36            0 :   auto design = m_readout.getNode("info.versions.design").read();
      37            0 :   auto major = m_readout.getNode("info.versions.major").read();
      38            0 :   auto minor = m_readout.getNode("info.versions.minor").read();
      39            0 :   auto patch = m_readout.getNode("info.versions.patch").read();
      40              : 
      41              : 
      42            0 :   auto n_mgt = m_readout.getNode("info.generics.n_mgts").read();
      43            0 :   auto n_src = m_readout.getNode("info.generics.n_srcs").read();
      44            0 :   auto ref_freq = m_readout.getNode("info.generics.ref_freq").read();
      45            0 :   m_readout.getClient().dispatch();
      46              : 
      47              :   // Version
      48            0 :   m_core_info.design = design.value();
      49            0 :   m_core_info.major = major.value();
      50            0 :   m_core_info.minor = minor.value();
      51            0 :   m_core_info.patch = patch.value();
      52              : 
      53              :   // Generics
      54            0 :   m_core_info.n_mgt = n_mgt.value();
      55            0 :   m_core_info.n_src = n_src.value();
      56            0 :   m_core_info.ref_freq = ref_freq.value();
      57              : 
      58              :   // Extra info
      59            0 :   m_core_info.srcs_per_mux = m_core_info.n_src;
      60              : 
      61            0 :   fmt::print("Number of links: {}\n", m_core_info.n_mgt);
      62            0 :   fmt::print("Number of sources: {}\n", m_core_info.n_src);
      63            0 :   fmt::print("Reference freq: {}\n", m_core_info.ref_freq);
      64            0 :   fmt::print("Sources per mux:{}\n",  m_core_info.srcs_per_mux);
      65              : 
      66            0 : }
      67              : 
      68              : 
      69              : //-----------------------------------------------------------------------------
      70              : void
      71            0 : HermesCoreController::sel_tx_mux(uint16_t i) {
      72            0 :   if ( i >= m_core_info.n_mgt ) {
      73            0 :     throw LinkDoesNotExist(ERS_HERE, i);
      74              :   }
      75              : 
      76            0 :   m_readout.getNode("tx_path.csr_tx_mux.ctrl.tx_mux_sel").write(i);
      77            0 :   m_readout.getClient().dispatch();
      78            0 : }
      79              : 
      80              : 
      81              : //-----------------------------------------------------------------------------
      82              : void
      83            0 : HermesCoreController::sel_tx_mux_buf(uint16_t i) {
      84            0 :   if ( i >= m_core_info.n_src ) {
      85            0 :     throw InputBufferDoesNotExist(ERS_HERE, i);
      86              :   }
      87              : 
      88            0 :   m_readout.getNode("tx_path.tx_mux.csr.ctrl.sel_buf").write(i);
      89            0 :   m_readout.getClient().dispatch();
      90            0 : }
      91              : 
      92              : 
      93              : //-----------------------------------------------------------------------------
      94              : void
      95            0 : HermesCoreController::sel_udp_core(uint16_t i) {
      96            0 :   if ( i >= m_core_info.n_mgt ) {
      97            0 :     throw MgtDoesNotExist(ERS_HERE, i);
      98              :   }
      99              : 
     100            0 :   m_readout.getNode("tx_path.csr_udp_core.ctrl.udp_core_sel").write(i);
     101            0 :   m_readout.getClient().dispatch();
     102            0 : }
     103              : 
     104              : 
     105              : //-----------------------------------------------------------------------------
     106              : void
     107            0 : HermesCoreController::reset(bool nuke) {
     108              : 
     109            0 :     if (nuke) {
     110            0 :         m_readout.getNode("csr.ctrl.nuke").write(0x1);
     111            0 :         m_readout.getClient().dispatch();
     112              : 
     113              :         // time.sleep(0.1);
     114            0 :         std::this_thread::sleep_for (std::chrono::milliseconds(1));
     115              : 
     116            0 :         m_readout.getNode("csr.ctrl.nuke").write(0x0);
     117            0 :         m_readout.getClient().dispatch();
     118              :     }
     119              :     
     120            0 :     m_readout.getNode("csr.ctrl.soft_rst").write(0x1);
     121            0 :     m_readout.getClient().dispatch();
     122              : 
     123              :     // time.sleep(0.1)
     124            0 :     std::this_thread::sleep_for (std::chrono::milliseconds(1));
     125              : 
     126              : 
     127            0 :     m_readout.getNode("csr.ctrl.soft_rst").write(0x0);
     128            0 :     m_readout.getClient().dispatch();
     129              : 
     130              :     // Check the ethernet core status
     131            0 :     auto eth_rdy = m_readout.getNode("tx_path.tx_mux.csr.stat.eth_rdy").read();
     132            0 :     m_readout.getClient().dispatch();
     133              : 
     134              :     // If the ethernet core is not ready, issue a phy reset
     135            0 :     if ( !eth_rdy ) {
     136            0 :       m_readout.getNode("pcs_pma.debug.csr.ctrl.phy_reset").write(0x1);
     137            0 :       m_readout.getNode("pcs_pma.debug.csr.ctrl.phy_reset").write(0x0);
     138            0 :       m_readout.getClient().dispatch();
     139              :     }
     140              : 
     141            0 : }
     142              : 
     143              : 
     144              : //-----------------------------------------------------------------------------
     145              : bool
     146            0 : HermesCoreController::is_link_in_error(uint16_t link, bool do_throw) {
     147              : 
     148            0 :   this->sel_tx_mux(link);
     149              : 
     150            0 :   auto& tx_mux_stat = m_readout.getNode("tx_path.tx_mux.csr.stat");
     151            0 :   auto err = tx_mux_stat.getNode("err").read();
     152            0 :   auto eth_rdy = tx_mux_stat.getNode("eth_rdy").read();
     153            0 :   auto src_rdy = tx_mux_stat.getNode("src_rdy").read();
     154            0 :   auto udp_rdy = tx_mux_stat.getNode("udp_rdy").read();
     155            0 :   tx_mux_stat.getClient().dispatch();
     156              : 
     157            0 :   bool is_error = (err || !eth_rdy || !src_rdy || !udp_rdy);
     158              : 
     159            0 :   if ( do_throw && is_error ) {
     160            0 :     throw LinkInError(ERS_HERE, link, err, eth_rdy, src_rdy, udp_rdy);
     161              :   }
     162              : 
     163            0 :   return is_error;
     164            0 : }
     165              : 
     166              : //-----------------------------------------------------------------------------
     167              : void
     168            0 : HermesCoreController::enable(uint16_t link, bool enable) {
     169              : 
     170            0 :   this->sel_tx_mux(link);
     171              : 
     172            0 :   auto& tx_mux_ctrl = m_readout.getNode("tx_path.tx_mux.csr.ctrl");
     173              :   
     174              :   // Not sure what to do with this
     175            0 :   auto tx_en = tx_mux_ctrl.getNode("tx_en").read();
     176            0 :   auto buf_en = tx_mux_ctrl.getNode("en_buf").read();
     177            0 :   auto ctrl_en = tx_mux_ctrl.getNode("en").read();
     178              : 
     179            0 :   if ( enable ) {
     180              : 
     181              :     // Assume that all is off
     182              : 
     183              :     // Enable the main logic
     184            0 :     tx_mux_ctrl.getNode("en").write(0x1);
     185            0 :     tx_mux_ctrl.getClient().dispatch();
     186              : 
     187              :     // Enable transmitter first
     188            0 :     tx_mux_ctrl.getNode("tx_en").write(0x1);
     189            0 :     tx_mux_ctrl.getClient().dispatch();
     190              : 
     191              :     // Enable buffers last
     192            0 :     tx_mux_ctrl.getNode("en_buf").write(0x1);
     193            0 :     tx_mux_ctrl.getClient().dispatch();
     194              : 
     195              : 
     196              :   } else {
     197              : 
     198              :     // Disable buffers last
     199            0 :     tx_mux_ctrl.getNode("en_buf").write(0x0);
     200            0 :     tx_mux_ctrl.getClient().dispatch();
     201              : 
     202              :     // Disable transmitter first
     203            0 :     tx_mux_ctrl.getNode("tx_en").write(0x0);
     204            0 :     tx_mux_ctrl.getClient().dispatch();
     205              : 
     206              :     // Disable the main logic
     207            0 :     tx_mux_ctrl.getNode("en").write(0x0);
     208            0 :     tx_mux_ctrl.getClient().dispatch();
     209              : 
     210              :   }
     211              : 
     212            0 : }
     213              : 
     214              : 
     215              : //-----------------------------------------------------------------------------
     216              : void
     217            0 : HermesCoreController::config_mux(uint16_t link, uint16_t det, uint16_t crate, uint16_t slot) {
     218            0 :   this->sel_tx_mux(link);
     219              : 
     220              : 
     221            0 :   auto& mux_ctrl = m_readout.getNode("tx_path.tx_mux.mux.ctrl");
     222              : 
     223            0 :   mux_ctrl.getNode("detid").write(det);
     224            0 :   mux_ctrl.getNode("crate").write(crate);
     225            0 :   mux_ctrl.getNode("slot").write(slot);
     226            0 :   mux_ctrl.getClient().dispatch();
     227              :     
     228            0 : }
     229              : 
     230              : 
     231              : //-----------------------------------------------------------------------------
     232              : void
     233            0 : HermesCoreController::config_udp( uint16_t link, uint64_t src_mac, uint32_t src_ip, uint16_t src_port, uint64_t dst_mac, uint32_t dst_ip, uint16_t dst_port, uint32_t filters) {
     234              : 
     235            0 :   if ( link >= m_core_info.n_mgt ) {
     236            0 :     throw LinkDoesNotExist(ERS_HERE, link);
     237              :   }
     238              : 
     239            0 :   this->sel_udp_core(link);
     240              : 
     241              :   // const std::string udp_ctrl_name = fmt::format("udp.udp_core_{}.udp_core_control.nz_rst_ctrl");
     242            0 :   const auto& udp_ctrl = m_readout.getNode("tx_path.udp_core.udp_core_control");
     243              : 
     244              : 
     245            0 :   udp_ctrl.getNode("src_addr_ctrl.use_external").write(0);  
     246              : 
     247              :   // Load the source mac address
     248            0 :   udp_ctrl.getNode("src_addr_ctrl.src_mac_addr_lower").write(src_mac & 0xffffffff);
     249            0 :   udp_ctrl.getNode("src_addr_ctrl.src_mac_addr_upper").write((src_mac >> 32) & 0xffff);
     250              : 
     251              :   // Load the source ip address
     252            0 :   udp_ctrl.getNode("src_addr_ctrl.src_ip_addr").write(src_ip);
     253              : 
     254              :   // Load the dst mac address
     255            0 :   udp_ctrl.getNode("ctrl.dst_mac_addr_lower").write(dst_mac & 0xffffffff);
     256            0 :   udp_ctrl.getNode("ctrl.dst_mac_addr_upper").write((dst_mac >> 32) & 0xffff);
     257              : 
     258              :   // Load the dst ip address
     259            0 :   udp_ctrl.getNode("ctrl.dst_ip_addr").write(dst_ip);
     260              : 
     261              :   // Ports
     262            0 :   udp_ctrl.getNode("src_addr_ctrl.src_port").write(src_port);
     263            0 :   udp_ctrl.getNode("ctrl.dst_port").write(dst_port);
     264              : 
     265              : 
     266            0 :   udp_ctrl.getNode("ctrl.filter_control").write(filters);
     267            0 :   udp_ctrl.getClient().dispatch();
     268              : 
     269            0 : }
     270              : 
     271              : //-----------------------------------------------------------------------------
     272              : void
     273            0 : HermesCoreController::config_fake_src(uint16_t link, uint16_t n_src, uint16_t data_len, uint16_t rate) {
     274              : 
     275            0 :   this->sel_tx_mux(link);
     276              : 
     277            0 :   auto was_en_buf = m_readout.getNode("tx_path.tx_mux.csr.ctrl.en_buf").read();
     278            0 :   m_readout.getNode("tx_path.tx_mux.csr.ctrl.en_buf").write(0x0);
     279            0 :   m_readout.getClient().dispatch();
     280              : 
     281              : 
     282              : 
     283            0 :   for ( size_t src_id(0); src_id<m_core_info.srcs_per_mux; ++src_id) {
     284            0 :     this->sel_tx_mux_buf(src_id);
     285              : 
     286              : 
     287            0 :     bool src_en = (src_id<n_src);
     288            0 :     m_readout.getNode("tx_path.tx_mux.buf.ctrl.fake_en").write(src_en);
     289            0 :     m_readout.getClient().dispatch();
     290            0 :     if (!src_en) {
     291            0 :       continue;
     292              :     }
     293            0 :     m_readout.getNode("tx_path.tx_mux.buf.ctrl.dlen").write(data_len);
     294              :         
     295            0 :     m_readout.getNode("tx_path.tx_mux.buf.ctrl.rate_rdx").write(rate);
     296            0 :     m_readout.getClient().dispatch();
     297              :   }
     298              : 
     299            0 :   m_readout.getNode("tx_path.tx_mux.csr.ctrl.en_buf").write(was_en_buf.value());
     300            0 :   m_readout.getClient().dispatch();
     301            0 : }
     302              : 
     303              : 
     304              : //-----------------------------------------------------------------------------
     305              : HermesCoreController::LinkGeoInfo
     306            0 : HermesCoreController::read_link_geo_info(uint16_t link) {
     307              : 
     308            0 :   this->sel_tx_mux(link);
     309              : 
     310            0 :   auto detid = m_readout.getNode("tx_path.tx_mux.mux.ctrl.detid").read();
     311            0 :   auto crate = m_readout.getNode("tx_path.tx_mux.mux.ctrl.crate").read();
     312            0 :   auto slot = m_readout.getNode("tx_path.tx_mux.mux.ctrl.slot").read();
     313              : 
     314            0 :   m_readout.getClient().dispatch();
     315              : 
     316            0 :   return {detid.value(), crate.value(), slot.value()};
     317            0 : }
     318              : 
     319              : //-----------------------------------------------------------------------------
     320              :   opmon::LinkInfo
     321            0 :   HermesCoreController::read_link_stats(uint16_t link) {
     322            0 :     this->sel_tx_mux(link);
     323            0 :     this->sel_udp_core(link);
     324              : 
     325            0 :     opmon::LinkInfo info;
     326              : 
     327            0 :     const auto& mux_stats = m_readout.getNode("tx_path.tx_mux.csr.stat");
     328            0 :     auto err = mux_stats.getNode("err").read();
     329            0 :     auto eth_rdy = mux_stats.getNode("eth_rdy").read();
     330            0 :     auto src_rdy = mux_stats.getNode("src_rdy").read();
     331            0 :     auto udp_rdy = mux_stats.getNode("udp_rdy").read();
     332            0 :     mux_stats.getClient().dispatch();
     333              : 
     334            0 :     const auto& udp_ctrl = m_readout.getNode(fmt::format("tx_path.udp_core.udp_core_control"));
     335            0 :     const auto& rx_stats = udp_ctrl.getNode("rx_packet_counters");
     336              : 
     337            0 :     auto rx_arp_count = rx_stats.getNode("arp_count").read();
     338            0 :     auto rx_ping_count = rx_stats.getNode("ping_count").read();
     339            0 :     auto rx_udp_count = rx_stats.getNode("udp_count").read();
     340            0 :     rx_stats.getClient().dispatch();
     341              : 
     342            0 :     const auto& tx_stats = udp_ctrl.getNode("tx_packet_counters");
     343              : 
     344            0 :     auto tx_arp_count = tx_stats.getNode("arp_count").read();
     345            0 :     auto tx_ping_count = tx_stats.getNode("ping_count").read();
     346            0 :     auto tx_udp_count = tx_stats.getNode("udp_count").read();
     347            0 :     tx_stats.getClient().dispatch();
     348              : 
     349              : 
     350            0 :     info.set_err(err.value());
     351            0 :     info.set_eth_rdy(eth_rdy.value());
     352            0 :     info.set_src_rdy(src_rdy.value());
     353            0 :     info.set_udp_rdy(udp_rdy.value());
     354              : 
     355            0 :     info.set_rcvd_arp_count(rx_arp_count.value());
     356            0 :     info.set_rcvd_ping_count(rx_ping_count.value());
     357            0 :     info.set_rcvd_udp_count(rx_udp_count.value());
     358              : 
     359            0 :     info.set_sent_arp_count(tx_arp_count.value());
     360            0 :     info.set_sent_ping_count(tx_ping_count.value());
     361            0 :     info.set_sent_udp_count(tx_udp_count.value());
     362              : 
     363            0 :     return info;
     364              : 
     365            0 :   }
     366              : 
     367              : }
     368              : }
        

Generated by: LCOV version 2.0-1