diff --git a/MuonSpectrometer/MuonCnv/MuonNSWCommonDecode/MuonNSWCommonDecode/NSWCommonDecoder.h b/MuonSpectrometer/MuonCnv/MuonNSWCommonDecode/MuonNSWCommonDecode/NSWCommonDecoder.h index 5c8a5be661a739ee16ce42e4936494f622a9edd2..cfbe955b3dc9d611478e7c2f933c9db1f9d9e256 100755 --- a/MuonSpectrometer/MuonCnv/MuonNSWCommonDecode/MuonNSWCommonDecode/NSWCommonDecoder.h +++ b/MuonSpectrometer/MuonCnv/MuonNSWCommonDecode/MuonNSWCommonDecode/NSWCommonDecoder.h @@ -25,7 +25,11 @@ namespace Muon const std::vector <Muon::nsw::NSWElink *> &get_elinks () const {return m_elinks;}; const std::vector <Muon::nsw::VMMChannel *> &get_channels () const {return m_channels;}; + bool has_error () {return m_has_error;}; + private: + bool m_has_error; + std::vector <Muon::nsw::NSWElink *> m_elinks; std::vector <Muon::nsw::VMMChannel *> m_channels; }; diff --git a/MuonSpectrometer/MuonCnv/MuonNSWCommonDecode/MuonNSWCommonDecode/NSWElink.h b/MuonSpectrometer/MuonCnv/MuonNSWCommonDecode/MuonNSWCommonDecode/NSWElink.h index 39e538e9d09024cd12894d177e61bb74abe7020c..12ae18c902394ccb6da3b464b0444d255db9b12e 100755 --- a/MuonSpectrometer/MuonCnv/MuonNSWCommonDecode/MuonNSWCommonDecode/NSWElink.h +++ b/MuonSpectrometer/MuonCnv/MuonNSWCommonDecode/MuonNSWCommonDecode/NSWElink.h @@ -6,6 +6,7 @@ #include <stdint.h> #include <vector> +#include <exception> #include "MuonNSWCommonDecode/NSWDecodeBitmaps.h" #include "MuonNSWCommonDecode/NSWDecodeHelper.h" @@ -17,11 +18,37 @@ namespace Muon class VMMChannel; class NSWResourceId; + class NSWElinkException: public std::exception + { + public: + explicit NSWElinkException (const char *s) + : m_description (s) {}; + + virtual const char *what () const throw () {return m_description.c_str ();}; + + private: + std::string m_description; + }; + + class NSWElinkROCHeaderException: public NSWElinkException + { + public: + explicit NSWElinkROCHeaderException (const char *s) + : NSWElinkException (s) {}; + }; + + class NSWElinkFelixHeaderException: public NSWElinkException + { + public: + explicit NSWElinkFelixHeaderException (const char *s) + : NSWElinkException (s) {}; + }; + class NSWElink { public: //NSWElink (); to be implemented for simulation - NSWElink (const uint32_t *bs); + NSWElink (const uint32_t *bs, uint32_t remaining); virtual ~NSWElink (); const std::vector <Muon::nsw::VMMChannel *> &get_channels () const {return m_channels;}; @@ -81,6 +108,8 @@ namespace Muon uint32_t m_elinkWord; Muon::nsw::NSWResourceId *m_elinkId; std::vector <Muon::nsw::VMMChannel *> m_channels; + + static const unsigned int s_null_packet_length = 10; }; } } diff --git a/MuonSpectrometer/MuonCnv/MuonNSWCommonDecode/MuonNSWCommonDecode/NSWResourceId.h b/MuonSpectrometer/MuonCnv/MuonNSWCommonDecode/MuonNSWCommonDecode/NSWResourceId.h index 183daacdd7111178d375a2f9a86bf63241cdc5fa..eecaa209abefc111a1a1a3b299b3289933e54e53 100644 --- a/MuonSpectrometer/MuonCnv/MuonNSWCommonDecode/MuonNSWCommonDecode/NSWResourceId.h +++ b/MuonSpectrometer/MuonCnv/MuonNSWCommonDecode/MuonNSWCommonDecode/NSWResourceId.h @@ -4,6 +4,7 @@ #ifndef _MUON_NSW_RESOURCE_ID_H_ #define _MUON_NSW_RESOURCE_ID_H_ +#include <iostream> #include "eformat/SourceIdentifier.h" #include "MuonNSWCommonDecode/NSWDecodeBitmaps.h" diff --git a/MuonSpectrometer/MuonCnv/MuonNSWCommonDecode/src/NSWCommonDecoder.cxx b/MuonSpectrometer/MuonCnv/MuonNSWCommonDecode/src/NSWCommonDecoder.cxx index d093f98d04859a93904c38ab07636af41f4b5e4e..66a572f3cee4bf1070845023adad41ad8809905e 100644 --- a/MuonSpectrometer/MuonCnv/MuonNSWCommonDecode/src/NSWCommonDecoder.cxx +++ b/MuonSpectrometer/MuonCnv/MuonNSWCommonDecode/src/NSWCommonDecoder.cxx @@ -9,6 +9,7 @@ #include "MuonNSWCommonDecode/NSWCommonDecoder.h" Muon::nsw::NSWCommonDecoder::NSWCommonDecoder (const eformat::read::ROBFragment &robFrag) + : m_has_error (false) { static const uint32_t s_min_packet_size = 3; // felix header + null ROC header @@ -16,32 +17,56 @@ Muon::nsw::NSWCommonDecoder::NSWCommonDecoder (const eformat::read::ROBFragment uint32_t nw = robFrag.rod_ndata (); const uint32_t *bs = robFrag.rod_data (); // point directly to the first data element - const uint32_t * current_data_pointer = const_cast <uint32_t *> (bs); + const uint32_t *current_data_pointer = const_cast <uint32_t *> (bs); uint32_t wcount(0); // data-element (32-bit word) counter ERS_DEBUG (1, "NDATA FROM ROB HEADER: " << nw); - while (nw - wcount >= s_min_packet_size) + uint32_t remaining = nw; + + while (remaining >= s_min_packet_size) { - Muon::nsw::NSWElink *elink = new Muon::nsw::NSWElink (current_data_pointer); - m_elinks.push_back (elink); + try + { + Muon::nsw::NSWElink *elink = new Muon::nsw::NSWElink (current_data_pointer, remaining); + m_elinks.push_back (elink); - // Append pointers to elink channels to a local channel vector + // Append pointers to elink channels to a local channel vector - const std::vector <Muon::nsw::VMMChannel *> vchan = elink->get_channels (); - for (auto i = vchan.begin (); i != vchan.end (); ++i) - m_channels.push_back (*i); + const std::vector <Muon::nsw::VMMChannel *> vchan = elink->get_channels (); + for (auto i = vchan.begin (); i != vchan.end (); ++i) + m_channels.push_back (*i); - wcount += elink->nwords (); - current_data_pointer += elink->nwords (); + wcount += elink->nwords (); + current_data_pointer += elink->nwords (); - ERS_DEBUG (1, "NDATA: " << nw << " WORD COUNTER: " << wcount); - ERS_DEBUG (1, "NPACKETS: " << m_elinks.size ()); - } + ERS_DEBUG (1, "NDATA: " << nw << " WORD COUNTER: " << wcount); + ERS_DEBUG (1, "NPACKETS: " << m_elinks.size ()); + + remaining = nw - wcount; + } + + catch (Muon::nsw::NSWElinkFelixHeaderException &e) + { + m_has_error = true; + //ers_error (e); + break; + } - if (wcount != nw) - throw EFORMAT_SIZE_CHECK (wcount, nw); + catch (Muon::nsw::NSWElinkROCHeaderException &e) + { + m_has_error = true; + //ers_error (e); + + // Try to move to next link + + wcount += s_min_packet_size; + current_data_pointer += s_min_packet_size; + remaining = nw - wcount; + continue; + } + } } Muon::nsw::NSWCommonDecoder::~NSWCommonDecoder () diff --git a/MuonSpectrometer/MuonCnv/MuonNSWCommonDecode/src/NSWElink.cxx b/MuonSpectrometer/MuonCnv/MuonNSWCommonDecode/src/NSWElink.cxx index 5c3e1977e4a2412713df4ca26eb10ef9bf009941..a6f44f18ae4322f2acac46699d49ca59a4f156c0 100644 --- a/MuonSpectrometer/MuonCnv/MuonNSWCommonDecode/src/NSWElink.cxx +++ b/MuonSpectrometer/MuonCnv/MuonNSWCommonDecode/src/NSWElink.cxx @@ -2,6 +2,8 @@ Copyright (C) 2002-2022 CERN for the benefit of the ATLAS collaboration */ #include <vector> +#include <exception> +#include <sstream> #include "ers/ers.h" @@ -12,7 +14,7 @@ #include "MuonNSWCommonDecode/VMMChannel.h" #include "MuonNSWCommonDecode/NSWResourceId.h" -Muon::nsw::NSWElink::NSWElink (const uint32_t *bs) +Muon::nsw::NSWElink::NSWElink (const uint32_t *bs, const uint32_t remaining) : m_wordCount (0) { // Felix header (2 words) @@ -22,6 +24,22 @@ Muon::nsw::NSWElink::NSWElink (const uint32_t *bs) unsigned int packet_nbytes = Muon::nsw::helper::get_bits (word, Muon::nsw::bitMaskFlxLENGTH, Muon::nsw::bitPosFlxLENGTH); m_packet_status = Muon::nsw::helper::get_bits (word, Muon::nsw::bitMaskFlxSTATUS, Muon::nsw::bitPosFlxSTATUS); + if (m_packet_status != 0) + { + std::ostringstream s; + s << "Packet status in FELIX header 0x" << std::hex << m_packet_status << std::dec; + Muon::nsw::NSWElinkFelixHeaderException e (s.str ().c_str ()); + throw e; + } + + if (remaining * sizeof (uint32_t) < packet_nbytes) + { + std::ostringstream s; + s << "Packet length in FELIX header " << packet_nbytes << " is larger than available data"; + Muon::nsw::NSWElinkFelixHeaderException e (s.str ().c_str ()); + throw e; + } + m_elinkWord = bs[m_wordCount++]; m_elinkId = new Muon::nsw::NSWResourceId (m_elinkWord); @@ -43,6 +61,17 @@ Muon::nsw::NSWElink::NSWElink (const uint32_t *bs) } else { + // It may happen that the null packet flag is wrong (or the size is wrong) + // In that case, throw an exception + + if (packet_nbytes == s_null_packet_length) + { + std::ostringstream s; + s << "Packet length in FELIX header " << packet_nbytes << " and null event flag in packet are inconsistent"; + Muon::nsw::NSWElinkROCHeaderException e (s.str ().c_str ()); + throw e; + } + // Calculate packet checksum const uint8_t *p = reinterpret_cast <const uint8_t *> (bs + 2); diff --git a/MuonSpectrometer/MuonCnv/MuonNSWCommonDecode/src/test/test_nsw_common_decoder.cxx b/MuonSpectrometer/MuonCnv/MuonNSWCommonDecode/src/test/test_nsw_common_decoder.cxx index 4222b55a44d7e50b52f0b53f3877e0b98ff23a09..263c432bdaa4d8a5e798bce1a1a9e5e77c4334bb 100644 --- a/MuonSpectrometer/MuonCnv/MuonNSWCommonDecode/src/test/test_nsw_common_decoder.cxx +++ b/MuonSpectrometer/MuonCnv/MuonNSWCommonDecode/src/test/test_nsw_common_decoder.cxx @@ -163,6 +163,9 @@ int test_nsw_common_decoder_event (eformat::read::FullEventFragment &f, const Pa if (nchan != nsw_decoder.get_channels ().size ()) ers::error (eformat::InconsistentChannelNumber (ERS_HERE, nchan, nsw_decoder.get_channels ().size ())); + if (params.printout_level > 2) + std::cout << "Hit number = " << nchan << std::endl; + // How to access information about detector elements and channels using the tree view if (params.tree_view)