LCOV - code coverage report
Current view: top level - tpglibs/src - TPGenerator.cpp (source / functions) Coverage Total Hit
Test: code.result Lines: 46.9 % 64 30
Test Date: 2025-12-21 13:07:08 Functions: 50.0 % 6 3

            Line data    Source code
       1              : /**
       2              :  * @file TPGenerator.hpp
       3              :  *
       4              :  * @copyright 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 "tpglibs/TPGenerator.hpp"
      10              : 
      11              : namespace tpglibs {
      12              : 
      13              : void
      14            3 : TPGenerator::configure(const std::vector<std::pair<std::string, nlohmann::json>>& configs,
      15              :                        const std::vector<std::pair<dunedaq::trgdataformats::channel_t, int16_t>> channel_plane_numbers,
      16              :                        const float sample_tick_difference) {
      17            3 :   if (m_configured) {
      18            0 :     reset();
      19              :   }
      20              : 
      21            3 :   m_num_pipelines = channel_plane_numbers.size() / m_num_channels_per_pipeline;
      22            3 :   m_sample_tick_difference = sample_tick_difference;
      23              : 
      24           15 :   for (int p = 0; p < m_num_pipelines; p++) {
      25           12 :     AVXPipeline new_pipe = AVXPipeline();
      26           12 :     auto begin_channel_plane = channel_plane_numbers.begin() + p*m_num_channels_per_pipeline;
      27           12 :     auto end_channel_plane = begin_channel_plane + m_num_channels_per_pipeline;
      28           12 :     new_pipe.configure(configs, std::vector<std::pair<dunedaq::trgdataformats::channel_t, int16_t>>(begin_channel_plane, end_channel_plane));
      29           12 :     new_pipe.set_sot_minima(m_sot_minima);
      30           12 :     m_tpg_pipelines.push_back(new_pipe);
      31           12 :   }
      32              : 
      33            3 :   m_configured = true;
      34            3 : }
      35              : 
      36            0 : std::vector<std::pair<std::shared_ptr<AbstractProcessor<__m256i>>, int>> TPGenerator::get_all_processor_references_with_pipeline_index() {
      37            0 :   std::vector<std::pair<std::shared_ptr<AbstractProcessor<__m256i>>, int>> processor_references;
      38              : 
      39            0 :   for (int pipeline_id = 0; pipeline_id < m_num_pipelines; ++pipeline_id) {
      40            0 :     for (auto& processor : m_tpg_pipelines[pipeline_id].get_all_processor_references()) {
      41            0 :       processor_references.push_back(std::make_pair(processor, pipeline_id));
      42            0 :     }
      43              :   }
      44            0 :   return processor_references;
      45            0 : }
      46              : 
      47              : void
      48            2 : TPGenerator::reset() {
      49            2 :   m_num_pipelines = 0;
      50            2 :   m_tpg_pipelines.clear();
      51            2 :   m_sample_tick_difference = 0;
      52            2 :   m_sot_minima = {1, 1, 1};
      53            2 :   m_configured = false;
      54            2 : }
      55              : 
      56              : void
      57            0 : TPGenerator::set_sot_minima(const std::vector<uint16_t>& sot_minima) {
      58            0 :   m_sot_minima = sot_minima;
      59            0 : }
      60              : 
      61              : 
      62              : __m256i
      63          768 : TPGenerator::expand_frame(const __m256i& regi) {
      64              :   // Refer to the diagram and documentation on frame expansion for details.
      65              : 
      66              :   // Prepare even (2,4,6,8), odd (1,3,5,7) rows in 64-bit sense.
      67          768 :   __m256i odd  = _mm256_permutevar8x32_epi32(regi, _mm256_setr_epi32(1, 0, 1, 2, 3, 4, 5, 6));
      68              : 
      69              :   // Shift into place.
      70          768 :   __m256i even = _mm256_sllv_epi64(regi, _mm256_setr_epi64x(6, 14, 22, 30));
      71          768 :   odd  = _mm256_srlv_epi64(odd, _mm256_setr_epi64x(30, 22, 14, 6));
      72              : 
      73              :   // Everything is center aligned in 32-bit. Mask and right-align the right side.
      74          768 :   __m256i both  = _mm256_blend_epi32(even, odd, 0b01010101);
      75          768 :   __m256i right = _mm256_and_si256(_mm256_set1_epi32(0xFFFFu), both);
      76          768 :   __m256i left  = _mm256_and_si256(_mm256_set1_epi32(0x3FFF0000u), both);
      77              : 
      78          768 :   right = _mm256_srli_epi32(right, 2);
      79          768 :   return _mm256_or_si256(left, right);
      80              : }
      81              : 
      82              : __m256i
      83            0 : TPGenerator::old_expand_frame(const __m256i& regi) {
      84              :   // Refer to the diagram and documentation on frame expansion for details.
      85              : 
      86              :   // Rearrange original with row 3 doubled.
      87            0 :   __m256i idx = _mm256_set_epi32(6, 5, 4, 3, 3, 2, 1, 0);
      88            0 :   __m256i shuf1 = _mm256_permutevar8x32_epi32(regi, idx);
      89              : 
      90              :   // Left shift each row.
      91            0 :   __m256i count = _mm256_set_epi32(12, 8, 4, 0, 14, 10, 6, 2);
      92            0 :   __m256i high_half = _mm256_sllv_epi32(shuf1, count);
      93            0 :   high_half = _mm256_and_si256(high_half, _mm256_set1_epi32(0x3FFF0000u));  // Mask out the low half.
      94              : 
      95              :   // Left shift for low half later.
      96            0 :   count = _mm256_set_epi32(10, 6, 2, 0, 12, 8, 4, 0);
      97            0 :   __m256i shift2 = _mm256_sllv_epi32(shuf1, count);
      98              : 
      99              :   // Rearrange original and doubled rows 2 and 0.
     100            0 :   idx = _mm256_set_epi32(5, 4, 3, 2, 2, 1, 0, 0);
     101            0 :   __m256i shuf2 = _mm256_permutevar8x32_epi32(regi, idx);
     102              : 
     103              :   // Right shift each row.
     104            0 :   count = _mm256_set_epi32(22, 26, 30, 0, 20, 24, 28, 0);
     105            0 :   __m256i shift3 = _mm256_srlv_epi32(shuf2, count);
     106              : 
     107              :   // "Complete" the low half. Still more.
     108            0 :   __m256i low_half = _mm256_or_si256(shift2, shift3);
     109            0 :   low_half = _mm256_and_si256(low_half, _mm256_set1_epi32(0x3FFFu)); // Mask out the high half.
     110              : 
     111              :   // Combine halves and clear space for an odd entry.
     112            0 :   __m256i both = _mm256_or_si256(low_half, high_half);
     113            0 :   both = _mm256_andnot_si256(_mm256_set_epi32(0, 0, 0, 0xFFFFu, 0, 0, 0, 0), both);
     114              : 
     115              :   // There is a specific 16-bit entry that needs special handling.
     116              :   // Align it.
     117            0 :   __m256i shift4 = _mm256_srli_epi32(regi, 18);
     118              :   // Mask it.
     119            0 :   shift4 = _mm256_and_si256(_mm256_set_epi32(0, 0x3FFFu, 0, 0, 0, 0, 0, 0), shift4);
     120              : 
     121              :   // Permute into the right spot
     122            0 :   idx = _mm256_set_epi32(0, 0, 0, 6, 0, 0, 0, 0);
     123            0 :   __m256i shuf3 = _mm256_permutevar8x32_epi32(shift4, idx);
     124              : 
     125              :   // Add it in.
     126            0 :   both = _mm256_or_si256(both, shuf3);
     127            0 :   return both;
     128              : }
     129              : 
     130              : 
     131              : } // namespace tpglibs
        

Generated by: LCOV version 2.0-1