LCOV - code coverage report
Current view: top level - src - l0id_decoder.cpp (source / functions) Hit Total Coverage
Test: coverage.info Lines: 7 148 4.7 %
Date: 2025-09-09 12:09:29 Functions: 1 9 11.1 %

          Line data    Source code
       1             : #include <cstring>
       2             : #include "l0id_decoder.hpp"
       3             : #include "log.hpp"
       4             : 
       5             : 
       6          25 : L0Decoder::L0Decoder(int format, uint64_t fid)
       7          25 :     : m_fid(fid)
       8             : {
       9          25 :     m_last.xl1id = 0x00ffffff;
      10             : 
      11          25 :     switch (format)
      12             :     {
      13             :     case 0:
      14             :         break;
      15           0 :     case L0ID_FMT::TTC2H:
      16           0 :         LOG_INFO("L1ID sequentiality check enabled: TTC2H only");
      17           0 :         check_sequence_error = std::bind(&L0Decoder::check_sequence_ttc2h, this, std::placeholders::_1, std::placeholders::_2);
      18           0 :         m_required_bytes = 8;
      19           0 :         m_ec_mask = 0x00ffffff;
      20           0 :         break;
      21           0 :     case L0ID_FMT::LATOME:
      22           0 :         LOG_INFO("L1ID sequentiality check enabled: TTC2H, LATOME data");
      23           0 :         check_sequence_error = std::bind(&L0Decoder::check_sequence_latome, this, std::placeholders::_1, std::placeholders::_2);
      24           0 :         m_required_bytes = 48;
      25           0 :         m_ec_mask = 0x00ffffff;
      26           0 :         break;
      27           0 :     case L0ID_FMT::FMEMU:
      28           0 :         LOG_INFO("L1ID sequentiality check enabled: TTC2H, FMEMU data");
      29           0 :         check_sequence_error = std::bind(&L0Decoder::check_sequence_fmemu, this, std::placeholders::_1, std::placeholders::_2);
      30           0 :         m_required_bytes = 4;
      31           0 :         m_ec_mask = 0x00ffffff;
      32           0 :         break;
      33           0 :     case L0ID_FMT::FELIG:
      34           0 :         LOG_INFO("L1ID sequentiality check enabled: TTC2H, FELIG data");
      35           0 :         check_sequence_error = std::bind(&L0Decoder::check_sequence_felig, this, std::placeholders::_1, std::placeholders::_2);
      36           0 :         m_required_bytes = 4;
      37           0 :         m_ec_mask = 0x0000ffff;
      38           0 :         break;
      39           0 :     case L0ID_FMT::NSW_VMM:
      40           0 :         LOG_INFO("L1ID sequentiality check enabled: TTC2H, NSW VMM data");
      41           0 :         check_sequence_error = std::bind(&L0Decoder::check_sequence_nsw_vmm, this, std::placeholders::_1, std::placeholders::_2);
      42           0 :         m_required_bytes = 4;
      43           0 :         m_ec_mask = 0x0000ffff;
      44           0 :         break;
      45           0 :     case L0ID_FMT::NSW_TP:
      46           0 :         LOG_INFO("L1ID sequentiality check enabled: TTC2H, NSW TP data");
      47           0 :         check_sequence_error = std::bind(&L0Decoder::check_sequence_nsw_tp, this, std::placeholders::_1, std::placeholders::_2);
      48           0 :         m_required_bytes = 8;
      49           0 :         m_ec_mask =  0x00ffffff;
      50           0 :         break;
      51          25 :     default:
      52          25 :         LOG_INFO("Invalid choice for L1ID sequentiality check. Check disabled");
      53             :     }
      54          25 : }
      55             : 
      56             : 
      57           0 : bool L0Decoder::check_tohost_chunk(std::vector<iovec> const &data)
      58             : {
      59           0 :     uint8_t* chunk = new uint8_t[m_required_bytes];
      60           0 :     unsigned int copied = 0;
      61           0 :     if (data.size() >= 1) {
      62           0 :         for (unsigned int idx = 1; idx < data.size(); ++idx) {
      63           0 :             unsigned int max = data[idx].iov_len > m_required_bytes ? m_required_bytes : data[idx].iov_len;
      64           0 :             memcpy(chunk + copied, data[idx].iov_base, max);
      65           0 :             copied += max;
      66           0 :             if (copied >= m_required_bytes){
      67             :                 break;
      68             :             }
      69             :         }
      70             :     }
      71           0 :     bool ret = check_sequence_error(chunk, copied);
      72           0 :     delete[] chunk;
      73           0 :     return ret;
      74             : }
      75             : 
      76             : 
      77           0 : bool inline L0Decoder::compare(xl1id_t current, xl1id_t expected)
      78             : {
      79           0 :   if(current.fields.ec != expected.fields.ec){
      80           0 :     LOG_INFO("fid 0x%lx (0x%x) has L1ID 0x%06x, expected 0x%06x", m_fid, get_elink(m_fid), current.fields.ec, expected.fields.ec);
      81           0 :     return true;
      82             :   }
      83             :   return false;
      84             : }
      85             : 
      86             : 
      87           0 : bool L0Decoder::check_sequence_ttc2h(const uint8_t* data, size_t len)
      88             : {
      89           0 :     if (len < m_required_bytes)
      90             :     {
      91           0 :         LOG_INFO("TTC2H message from fid 0x%lx (0x%x) too small to retrieve XL1ID, size %lu.", m_fid, get_elink(m_fid), len);
      92           0 :         return true;
      93             :     }
      94           0 :     xl1id_t current, expected;
      95           0 :     current.xl1id = reinterpret_cast<const uint32_t *>(data)[1];
      96             : 
      97           0 :     bcid_t current_bc;
      98           0 :     current_bc.bc_data = reinterpret_cast<const uint32_t *>(data)[0];
      99             : 
     100           0 :     LOG_DBG("Current L1ID 0x%06x BCID 0x%04x", current.fields.ec, current_bc.fields.bcid);
     101           0 :     if (current.fields.ecrc == (m_last.fields.ecrc + 1))
     102             :     {
     103           0 :         LOG_INFO("ECR on TTC2H fid 0x%lx (0x%x)", m_fid, get_elink(m_fid));
     104           0 :         expected.fields.ec = 0x0;
     105             :     }
     106             :     else
     107             :     {
     108           0 :         expected.fields.ec = (m_last.fields.ec + 1) & 0x00ffffff;
     109             :     }
     110           0 :     m_last.xl1id = current.xl1id;
     111           0 :     return compare(current, expected);
     112             : }
     113             : 
     114             : 
     115           0 : bool L0Decoder::check_sequence_latome(const uint8_t* data, size_t len)
     116             : {
     117           0 :     if (len < m_required_bytes)
     118             :     {
     119           0 :         LOG_INFO("LATOME message from fid 0x%lx (0x%x) too small to retrieve XL1ID, size %lu.", m_fid, get_elink(m_fid), len);
     120           0 :         return true;
     121             :     }
     122           0 :     xl1id_t current, expected;
     123           0 :     current.xl1id = reinterpret_cast<const uint32_t *>(data)[5];
     124             : 
     125           0 :     if (current.fields.ecrc == (m_last.fields.ecrc + 1))
     126             :     {
     127           0 :         LOG_DBG("ECR on fid 0x%lx (0x%x)", m_fid, get_elink(m_fid));
     128           0 :         expected.fields.ec = 0x0;
     129             :     }
     130             :     else
     131             :     {
     132           0 :         expected.fields.ec = (m_last.fields.ec + 1) & 0x00ffffff;
     133             :     }
     134           0 :     m_last.xl1id = current.xl1id;
     135           0 :     return compare(current, expected);
     136             : }
     137             : 
     138             : 
     139           0 : bool L0Decoder::check_sequence_fmemu(const uint8_t* data, size_t len)
     140             : {
     141           0 :     if (len < m_required_bytes)
     142             :     {
     143           0 :         LOG_INFO("FMEMU message from fid 0x%lx (0x%x) too small to retrieve XL1ID, size %lu.", m_fid, get_elink(m_fid), len);
     144           0 :         return true;
     145             :     }
     146           0 :     xl1id_t current, expected;
     147           0 :     current.xl1id = reinterpret_cast<const uint32_t *>(data)[0];
     148           0 :     if (current.fields.ecrc == (m_last.fields.ecrc + 1))
     149             :     {
     150           0 :         LOG_DBG("ECR on fid 0x%lx (0x%x)", m_fid, get_elink(m_fid));
     151           0 :         expected.fields.ec = 0x0;
     152             :     }
     153             :     else
     154             :     {
     155           0 :         expected.fields.ec = (m_last.fields.ec + 1) & 0x00ffffff;
     156             :     }
     157           0 :     m_last.xl1id = current.xl1id;
     158           0 :     return compare(current, expected);
     159             : }
     160             : 
     161             : 
     162           0 : bool L0Decoder::check_sequence_felig(const uint8_t* data, size_t len)
     163             : {
     164           0 :     if (len < m_required_bytes)
     165             :     {
     166           0 :         LOG_INFO("FELIG message from fid 0x%lx (0x%x) smaller than FELIG header, size %lu.", m_fid, get_elink(m_fid), len);
     167           0 :         return true;
     168             :     }
     169           0 :     xl1id_t current, expected;
     170           0 :     uint8_t* chunk_data = const_cast<uint8_t*>(data);
     171           0 :     current.fields.ec = ( chunk_data[4] | (chunk_data[3] << 8) );
     172           0 :     expected.fields.ec = (m_last.fields.ec + 1) & 0x0000ffff;
     173           0 :     m_last.xl1id = current.xl1id;
     174           0 :     return compare(current, expected);
     175             : }
     176             : 
     177             : 
     178           0 : bool L0Decoder::check_sequence_nsw_vmm(const uint8_t* data, size_t len)
     179             : {
     180           0 :     if (len < 2){
     181           0 :         LOG_INFO("NSW VMM message from fid 0x%lx (0x%x) too small to retrieve header, size %lu.",
     182             :             m_fid, get_elink(m_fid), len);
     183           0 :         return true;
     184             :     }
     185           0 :     if (len > 4*(512+4)) {
     186           0 :         LOG_INFO("NSW VMM message from fid 0x%lx (0x%x) too long, size %lu.", m_fid, get_elink(m_fid), len);
     187             :     }
     188           0 :     xl1id_t current, expected;
     189             :     //enum packetType { FULL_MM=0, NULL_EVENT=1, FULL_STGC=2 , ILLEGAL=3};
     190           0 :     unsigned char headerType = data[0] >> 6;
     191           0 :     switch (headerType)
     192             :     {
     193           0 :     case 0: // MM   full header
     194           0 :     case 2: // sTGC full header
     195           0 :         current.fields.ec = (data[3] | (data[2] << 8)) & 0xff;
     196           0 :         expected.fields.ec = (m_last.fields.ec + 1) & 0xff;
     197           0 :         m_last.fields.ec = (data[3] | (data[2] << 8)) & 0xffff;
     198           0 :         m_ec_mask = 0xffff;
     199           0 :         break;
     200           0 :     case 1: // null header
     201           0 :         current.fields.ec = data[1];
     202           0 :         expected.fields.ec = (m_last.fields.ec + 1) & 0xff;
     203           0 :         m_last.fields.ec = data[1];
     204           0 :         m_ec_mask = 0xff;
     205           0 :         break;
     206           0 :     case 3: // illegal header type
     207           0 :     {
     208           0 :         unsigned int vmmHeader = (data[0] << 24) | (data[1] << 16) | (data[2] << 8) | data[3];
     209           0 :         LOG_INFO("Illegal VMM message from fid 0x%lx (0x%x), headerType = 3, headerword = 0x%x, size %d.", m_fid, get_elink(m_fid), vmmHeader, len);
     210             :         break;
     211             :     }
     212           0 :     default:
     213           0 :         LOG_INFO("Invalid header from fid 0x%lx (0x%x), type 0x%x", m_fid, get_elink(m_fid), headerType);
     214             :     }
     215             : 
     216           0 :     return compare(current, expected);
     217             : }
     218             : 
     219             : 
     220           0 : bool L0Decoder::check_sequence_nsw_tp(const uint8_t* data, size_t len)
     221             : {
     222           0 :     if (len < m_required_bytes)
     223             :     {
     224           0 :         LOG_INFO("NSW TP message from fid 0x%lx (0x%x) too small to retrieve XL1ID, size %lu.", m_fid, get_elink(m_fid), len);
     225           0 :         return true;
     226             :     }
     227           0 :     xl1id_t current, expected;
     228           0 :     current.fields.ec =  ( data[5]<<16 | data[6]<<8 | data[7] ) & 0x00ffffff;
     229           0 :     current.fields.ecrc = (data[4]<<24) & 0xff;
     230           0 :     if(current.fields.ecrc == (m_last.fields.ecrc+1) ){
     231             :       LOG_DBG("ECR on fid 0x%lx (0x%x)", m_fid, get_elink(m_fid));
     232             :       expected.fields.ec = 0x0;
     233             :     } else{
     234           0 :       expected.fields.ec = (m_last.fields.ec+1) & 0x00ffffff;
     235             :     }
     236           0 :     m_last.xl1id = current.xl1id;
     237           0 :     return compare(current, expected);
     238             : }

Generated by: LCOV version 1.0