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: 2026-10-11 15:05:20 Functions: 0.0 % 14 0

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

Generated by: LCOV version 2.0-1