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

            Line data    Source code
       1              : /**
       2              :  * @file FLCmdGeneratorNode.cpp
       3              :  *
       4              :  * This is part of the DUNE DAQ Software Suite, copyright 2020.
       5              :  * Licensing/copyright details are in the COPYING file that you should have
       6              :  * received with this code.
       7              :  */
       8              : 
       9              : #include "timing/FLCmdGeneratorNode.hpp"
      10              : 
      11              : #include "timing/toolbox.hpp"
      12              : #include "logging/Logging.hpp"
      13              : 
      14              : #include <string>
      15              : #include <vector>
      16              : 
      17              : namespace dunedaq {
      18              : namespace timing {
      19              : 
      20            0 : UHAL_REGISTER_DERIVED_NODE(FLCmdGeneratorNode)
      21              : 
      22              : //-----------------------------------------------------------------------------
      23            0 : FLCmdGeneratorNode::FLCmdGeneratorNode(const uhal::Node& node)
      24            0 :   : TimingNode(node)
      25            0 : {}
      26              : //-----------------------------------------------------------------------------
      27              : 
      28              : //-----------------------------------------------------------------------------
      29            0 : FLCmdGeneratorNode::~FLCmdGeneratorNode() {}
      30              : //-----------------------------------------------------------------------------
      31              : 
      32              : //-----------------------------------------------------------------------------
      33              : std::string
      34            0 : FLCmdGeneratorNode::get_status(bool print_out) const
      35              : {
      36            0 :   std::stringstream status;
      37            0 :   auto subnodes = read_sub_nodes(getNode("csr.stat"));
      38            0 :   status << format_reg_table(subnodes, "FL Cmd gen state");
      39            0 :   if (print_out)
      40            0 :     TLOG() << status.str();
      41            0 :   return status.str();
      42            0 : }
      43              : //-----------------------------------------------------------------------------
      44              : 
      45              : //-----------------------------------------------------------------------------
      46              : void
      47            0 : FLCmdGeneratorNode::validate_command(uint32_t command) const // NOLINT(build/unsigned)
      48              : {
      49            0 :   if (command > 0xff)
      50              :   {
      51            0 :     throw InvalidFixedLatencyCommand(ERS_HERE, command);
      52              :   }
      53            0 : }
      54              : //-----------------------------------------------------------------------------
      55              : 
      56              : //-----------------------------------------------------------------------------
      57              : void
      58            0 : FLCmdGeneratorNode::validate_channel(uint32_t channel) const // NOLINT(build/unsigned)
      59              : {
      60            0 :   if (channel > 0x4)
      61              :   {
      62            0 :     throw InvalidFixedLatencyCommandChannel(ERS_HERE, channel);
      63              :   }
      64            0 : }
      65              : //-----------------------------------------------------------------------------
      66              : 
      67              : //-----------------------------------------------------------------------------
      68              : void
      69            0 : FLCmdGeneratorNode::send_fl_cmd(uint32_t command,       // NOLINT(build/unsigned)
      70              :                                 uint32_t channel) const // NOLINT(build/unsigned)
      71              : {
      72            0 :   validate_command(command);
      73            0 :   validate_channel(channel);
      74              : 
      75            0 :   getNode("sel").write(channel);
      76              : 
      77            0 :   reset_sub_nodes(getNode("chan_ctrl"));
      78              : 
      79            0 :   getNode("chan_ctrl.type").write(command);
      80            0 :   getNode("ctrl.force").write(0x1);
      81            0 :   getClient().dispatch();
      82              : 
      83            0 :   getNode("ctrl.force").write(0x0);
      84            0 :   getClient().dispatch();
      85            0 : }
      86              : //-----------------------------------------------------------------------------
      87              : 
      88              : //-----------------------------------------------------------------------------
      89              : void
      90            0 : FLCmdGeneratorNode::enable_periodic_fl_cmd(uint32_t channel,  // NOLINT(build/unsigned)
      91              :                                            double rate,
      92              :                                            bool poisson,
      93              :                                            uint32_t clock_frequency_hz) const
      94              : {
      95            0 :   enable_periodic_fl_cmd(0x8+channel, channel, rate, poisson, clock_frequency_hz);
      96            0 : }
      97              : //-----------------------------------------------------------------------------
      98              : 
      99              : //-----------------------------------------------------------------------------
     100              : void
     101            0 : FLCmdGeneratorNode::enable_periodic_fl_cmd(uint32_t command,  // NOLINT(build/unsigned)
     102              :                                            uint32_t channel,  // NOLINT(build/unsigned)
     103              :                                            double rate,
     104              :                                            bool poisson,
     105              :                                            uint32_t clock_frequency_hz) const
     106              : {
     107            0 :   uint32_t divisor;
     108            0 :   uint32_t prescale;
     109            0 :   double actual_rate;
     110              : 
     111            0 :   parse_periodic_fl_cmd_rate(rate, clock_frequency_hz, actual_rate, divisor, prescale);
     112              : 
     113            0 :   TLOG() << "Requested rate, actual rate: " << rate << ", " << actual_rate;
     114            0 :   TLOG() << "prescale, divisor: " << prescale << ", " << divisor;
     115              : 
     116            0 :   std::stringstream trig_stream;
     117            0 :   trig_stream << "> Periodic rate for command 0x" << std::hex << command << ", on channel 0x" << channel
     118            0 :               << " set to " << std::setprecision(3) << std::scientific << actual_rate << " Hz";
     119            0 :   TLOG() << trig_stream.str();
     120              : 
     121            0 :   std::stringstream trigger_mode_stream;
     122            0 :   trigger_mode_stream << "> Trigger mode: ";
     123              : 
     124            0 :   if (poisson) {
     125            0 :     trigger_mode_stream << "poisson";
     126              :   } else {
     127            0 :     trigger_mode_stream << "periodic";
     128              :   }
     129            0 :   TLOG() << trigger_mode_stream.str();
     130            0 :   enable_periodic_fl_cmd(command, channel, divisor, prescale, poisson);
     131              : 
     132            0 : }
     133              : //-----------------------------------------------------------------------------
     134              : 
     135              : //-----------------------------------------------------------------------------
     136              : void
     137            0 : FLCmdGeneratorNode::enable_periodic_fl_cmd(uint32_t channel,  // NOLINT(build/unsigned)
     138              :                                         uint32_t divisor,  // NOLINT(build/unsigned)
     139              :                                         uint32_t prescale, // NOLINT(build/unsigned)
     140              :                                         bool poisson) const
     141              : {
     142            0 :   enable_periodic_fl_cmd(0x8+channel, channel, divisor, prescale, poisson);
     143            0 : }
     144              : //-----------------------------------------------------------------------------
     145              : 
     146              : //-----------------------------------------------------------------------------
     147              : void
     148            0 : FLCmdGeneratorNode::enable_periodic_fl_cmd(uint32_t command,  // NOLINT(build/unsigned)
     149              :                                         uint32_t channel,  // NOLINT(build/unsigned)
     150              :                                         uint32_t divisor,  // NOLINT(build/unsigned)
     151              :                                         uint32_t prescale, // NOLINT(build/unsigned)
     152              :                                         bool poisson) const
     153              : {
     154            0 :   validate_command(command);
     155            0 :   validate_channel(channel);
     156              : 
     157            0 :   getNode("sel").write(channel);
     158              : 
     159            0 :   getNode("chan_ctrl.type").write(command);
     160            0 :   getNode("chan_ctrl.rate_div_d").write(divisor);
     161            0 :   getNode("chan_ctrl.rate_div_p").write(prescale);
     162            0 :   getNode("chan_ctrl.patt").write(poisson);
     163            0 :   getNode("chan_ctrl.en").write(1); // Start the command stream
     164            0 :   getClient().dispatch();
     165            0 : }
     166              : //-----------------------------------------------------------------------------
     167              : 
     168              : //-----------------------------------------------------------------------------
     169              : void
     170            0 : FLCmdGeneratorNode::disable_fake_trigger(uint32_t channel) const // NOLINT(build/unsigned)
     171              : {
     172            0 :   validate_channel(channel);
     173              : 
     174              :   // Clear the internal trigger generator.
     175            0 :   getNode("sel").write(channel);
     176            0 :   reset_sub_nodes(getNode("chan_ctrl"));
     177            0 :   TLOG() << "Fake trigger generator " << format_reg_value(channel) << " configuration cleared";
     178            0 : }
     179              : //------------------------------------------------------------------------------
     180              : 
     181              : //------------------------------------------------------------------------------
     182              : std::string
     183            0 : FLCmdGeneratorNode::get_cmd_counters_table(bool print_out) const
     184              : {
     185            0 :   std::stringstream counters_table;
     186            0 :   auto accepted_counters = getNode("actrs").readBlock(getNode("actrs").getSize());
     187            0 :   auto rejected_counters = getNode("rctrs").readBlock(getNode("actrs").getSize());
     188            0 :   getClient().dispatch();
     189              : 
     190            0 :   std::vector<uhal::ValVector<uint32_t>> counters_container = { accepted_counters, rejected_counters }; // NOLINT(build/unsigned)
     191              : 
     192            0 :   counters_table << format_counters_table(counters_container,
     193              :                                           { "Accept counters", "Reject counters" },
     194              :                                           "Cmd gen counters",
     195              :                                           { "0x0", "0x1", "0x2", "0x3", "0x4" },
     196            0 :                                           "Chan");
     197              : 
     198            0 :   if (print_out)
     199            0 :     TLOG() << counters_table.str();
     200            0 :   return counters_table.str();
     201            0 : }
     202              : //-----------------------------------------------------------------------------
     203              : 
     204              : //-----------------------------------------------------------------------------
     205              : // void
     206              : // FLCmdGeneratorNode::get_info(opmonlib::InfoCollector& ic, int /*level*/) const
     207              : // {
     208              : //   auto accepted_counters = getNode("actrs").readBlock(getNode("actrs").getSize());
     209              : //   auto rejected_counters = getNode("rctrs").readBlock(getNode("actrs").getSize());
     210              : //   getClient().dispatch();
     211              : 
     212              : //   uint number_of_channels = 5;
     213              : 
     214              : //   for (uint i = 0; i < number_of_channels; ++i) { // NOLINT(build/unsigned)
     215              : 
     216              : //     timingfirmwareinfo::TimingFLCmdCounter cmd_counter;
     217              : //     opmonlib::InfoCollector cmd_counter_ic;
     218              : 
     219              : //     cmd_counter.accepted = accepted_counters.at(i);
     220              : //     cmd_counter.rejected = rejected_counters.at(i);
     221              : 
     222              : //     std::string channel = "fl_cmd_channel_" + std::to_string(i);
     223              : 
     224              : //     cmd_counter_ic.add(cmd_counter);
     225              : //     ic.add(channel, cmd_counter_ic);
     226              : //   }
     227              : // }
     228              : //-----------------------------------------------------------------------------
     229              : 
     230              : //-----------------------------------------------------------------------------
     231            0 : void FLCmdGeneratorNode::parse_periodic_fl_cmd_rate(double requested_rate,
     232              :                                                     uint32_t clock_frequency_hz,
     233              :                                                     double& actual_rate,
     234              :                                                     uint32_t& divisor,
     235              :                                                     uint32_t& prescale)
     236              : {
     237              :   // Rate =  (clock_frequency_hz / 2^(d+8)) / p where n in [0,15] and p in [1,256]
     238              : 
     239              :   // DIVIDER (int): Frequency divider.
     240              : 
     241              :   // The division from clock_frequency_hz to the desired rate is done in three steps:
     242              :   // a) A pre-division by 256
     243              :   // b) Division by a power of two set by n = 2 ^ rate_div_d (ranging from 2^0 -> 2^15)
     244              :   // c) 1-in-n prescaling set by n = rate_div_p
     245              : 
     246            0 :   double div = ceil(log(clock_frequency_hz / (requested_rate * 256 * 256)) / log(2));
     247            0 :   if (div < 0) {
     248            0 :     divisor = 0;
     249            0 :   } else if (div > 15) {
     250            0 :     divisor = 15;
     251              :   } else {
     252            0 :     divisor = div;
     253              :   }
     254              : 
     255            0 :   uint32_t ps = (uint32_t)((clock_frequency_hz / (requested_rate * 256 * (1 << divisor))) + 0.5); // NOLINT(build/unsigned)
     256            0 :   if (ps == 0 || ps > 256)
     257              :   {
     258            0 :     throw BadRequestedFakeTriggerRate(ERS_HERE, requested_rate, ps);
     259              :   } else {
     260            0 :     prescale = ps;
     261              :   }
     262            0 :   actual_rate = static_cast<double>(clock_frequency_hz) / (256 * prescale * (1 << divisor));
     263            0 : }
     264              : //-----------------------------------------------------------------------------
     265              : 
     266              : } // namespace timing
     267              : } // namespace dunedaq
        

Generated by: LCOV version 2.0-1