.. _program_listing_file_l0id_decoder.cpp: Program Listing for File l0id_decoder.cpp ========================================= |exhale_lsh| :ref:`Return to documentation for file ` (``l0id_decoder.cpp``) .. |exhale_lsh| unicode:: U+021B0 .. UPWARDS ARROW WITH TIP LEFTWARDS .. code-block:: cpp #include #include "l0id_decoder.hpp" #include "log.hpp" L0Decoder::L0Decoder(int format, uint64_t fid) : m_fid(fid) { m_last.xl1id = 0x00ffffff; switch (format) { case 0: break; case L0ID_FMT::TTC2H: LOG_INFO("L1ID sequentiality check enabled: TTC2H only"); check_sequence_error = std::bind(&L0Decoder::check_sequence_ttc2h, this, std::placeholders::_1, std::placeholders::_2); m_required_bytes = 8; m_ec_mask = 0x00ffffff; break; case L0ID_FMT::LATOME: LOG_INFO("L1ID sequentiality check enabled: TTC2H, LATOME data"); check_sequence_error = std::bind(&L0Decoder::check_sequence_latome, this, std::placeholders::_1, std::placeholders::_2); m_required_bytes = 48; m_ec_mask = 0x00ffffff; break; case L0ID_FMT::FMEMU: LOG_INFO("L1ID sequentiality check enabled: TTC2H, FMEMU data"); check_sequence_error = std::bind(&L0Decoder::check_sequence_fmemu, this, std::placeholders::_1, std::placeholders::_2); m_required_bytes = 4; m_ec_mask = 0x00ffffff; break; case L0ID_FMT::FELIG: LOG_INFO("L1ID sequentiality check enabled: TTC2H, FELIG data"); check_sequence_error = std::bind(&L0Decoder::check_sequence_felig, this, std::placeholders::_1, std::placeholders::_2); m_required_bytes = 4; m_ec_mask = 0x0000ffff; break; case L0ID_FMT::NSW_VMM: LOG_INFO("L1ID sequentiality check enabled: TTC2H, NSW VMM data"); check_sequence_error = std::bind(&L0Decoder::check_sequence_nsw_vmm, this, std::placeholders::_1, std::placeholders::_2); m_required_bytes = 4; m_ec_mask = 0x0000ffff; break; case L0ID_FMT::NSW_TP: LOG_INFO("L1ID sequentiality check enabled: TTC2H, NSW TP data"); check_sequence_error = std::bind(&L0Decoder::check_sequence_nsw_tp, this, std::placeholders::_1, std::placeholders::_2); m_required_bytes = 8; m_ec_mask = 0x00ffffff; break; default: LOG_INFO("Invalid choice for L1ID sequentiality check. Check disabled"); } } bool L0Decoder::check_tohost_chunk(std::vector const &data) { uint8_t* chunk = new uint8_t[m_required_bytes]; unsigned int copied = 0; if (data.size() >= 1) { for (unsigned int idx = 1; idx < data.size(); ++idx) { unsigned int max = data[idx].iov_len > m_required_bytes ? m_required_bytes : data[idx].iov_len; memcpy(chunk + copied, data[idx].iov_base, max); copied += max; if (copied >= m_required_bytes){ break; } } } bool ret = check_sequence_error(chunk, copied); delete[] chunk; return ret; } bool inline L0Decoder::compare(xl1id_t current, xl1id_t expected) { if(current.fields.ec != expected.fields.ec){ 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); return true; } return false; } bool L0Decoder::check_sequence_ttc2h(const uint8_t* data, size_t len) { if (len < m_required_bytes) { LOG_INFO("TTC2H message from fid 0x%lx (0x%x) too small to retrieve XL1ID, size %lu.", m_fid, get_elink(m_fid), len); return true; } xl1id_t current, expected; current.xl1id = reinterpret_cast(data)[1]; bcid_t current_bc; current_bc.bc_data = reinterpret_cast(data)[0]; LOG_DBG("Current L1ID 0x%06x BCID 0x%04x", current.fields.ec, current_bc.fields.bcid); if (current.fields.ecrc == (m_last.fields.ecrc + 1)) { LOG_INFO("ECR on TTC2H fid 0x%lx (0x%x)", m_fid, get_elink(m_fid)); expected.fields.ec = 0x0; } else { expected.fields.ec = (m_last.fields.ec + 1) & 0x00ffffff; } m_last.xl1id = current.xl1id; return compare(current, expected); } bool L0Decoder::check_sequence_latome(const uint8_t* data, size_t len) { if (len < m_required_bytes) { LOG_INFO("LATOME message from fid 0x%lx (0x%x) too small to retrieve XL1ID, size %lu.", m_fid, get_elink(m_fid), len); return true; } xl1id_t current, expected; current.xl1id = reinterpret_cast(data)[5]; if (current.fields.ecrc == (m_last.fields.ecrc + 1)) { LOG_DBG("ECR on fid 0x%lx (0x%x)", m_fid, get_elink(m_fid)); expected.fields.ec = 0x0; } else { expected.fields.ec = (m_last.fields.ec + 1) & 0x00ffffff; } m_last.xl1id = current.xl1id; return compare(current, expected); } bool L0Decoder::check_sequence_fmemu(const uint8_t* data, size_t len) { if (len < m_required_bytes) { LOG_INFO("FMEMU message from fid 0x%lx (0x%x) too small to retrieve XL1ID, size %lu.", m_fid, get_elink(m_fid), len); return true; } xl1id_t current, expected; current.xl1id = reinterpret_cast(data)[0]; if (current.fields.ecrc == (m_last.fields.ecrc + 1)) { LOG_DBG("ECR on fid 0x%lx (0x%x)", m_fid, get_elink(m_fid)); expected.fields.ec = 0x0; } else { expected.fields.ec = (m_last.fields.ec + 1) & 0x00ffffff; } m_last.xl1id = current.xl1id; return compare(current, expected); } bool L0Decoder::check_sequence_felig(const uint8_t* data, size_t len) { if (len < m_required_bytes) { LOG_INFO("FELIG message from fid 0x%lx (0x%x) smaller than FELIG header, size %lu.", m_fid, get_elink(m_fid), len); return true; } xl1id_t current, expected; uint8_t* chunk_data = const_cast(data); current.fields.ec = ( chunk_data[4] | (chunk_data[3] << 8) ); expected.fields.ec = (m_last.fields.ec + 1) & 0x0000ffff; m_last.xl1id = current.xl1id; return compare(current, expected); } bool L0Decoder::check_sequence_nsw_vmm(const uint8_t* data, size_t len) { if (len < 2){ LOG_INFO("NSW VMM message from fid 0x%lx (0x%x) too small to retrieve header, size %lu.", m_fid, get_elink(m_fid), len); return true; } if (len > 4*(512+4)) { LOG_INFO("NSW VMM message from fid 0x%lx (0x%x) too long, size %lu.", m_fid, get_elink(m_fid), len); } xl1id_t current, expected; //enum packetType { FULL_MM=0, NULL_EVENT=1, FULL_STGC=2 , ILLEGAL=3}; unsigned char headerType = data[0] >> 6; switch (headerType) { case 0: // MM full header case 2: // sTGC full header current.fields.ec = (data[3] | (data[2] << 8)) & 0xff; expected.fields.ec = (m_last.fields.ec + 1) & 0xff; m_last.fields.ec = (data[3] | (data[2] << 8)) & 0xffff; m_ec_mask = 0xffff; break; case 1: // null header current.fields.ec = data[1]; expected.fields.ec = (m_last.fields.ec + 1) & 0xff; m_last.fields.ec = data[1]; m_ec_mask = 0xff; break; case 3: // illegal header type { unsigned int vmmHeader = (data[0] << 24) | (data[1] << 16) | (data[2] << 8) | data[3]; 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); break; } default: LOG_INFO("Invalid header from fid 0x%lx (0x%x), type 0x%x", m_fid, get_elink(m_fid), headerType); } return compare(current, expected); } bool L0Decoder::check_sequence_nsw_tp(const uint8_t* data, size_t len) { if (len < m_required_bytes) { 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); return true; } xl1id_t current, expected; current.fields.ec = ( data[5]<<16 | data[6]<<8 | data[7] ) & 0x00ffffff; current.fields.ecrc = (data[4]<<24) & 0xff; if(current.fields.ecrc == (m_last.fields.ecrc+1) ){ LOG_DBG("ECR on fid 0x%lx (0x%x)", m_fid, get_elink(m_fid)); expected.fields.ec = 0x0; } else{ expected.fields.ec = (m_last.fields.ec+1) & 0x00ffffff; } m_last.xl1id = current.xl1id; return compare(current, expected); }