Back to home page

Project CMSSW displayed by LXR

 
 

    


File indexing completed on 2025-06-28 06:19:01

0001 #ifndef DataFormats_FEDRawData_SLinkRocketHeaders_h
0002 #define DataFormats_FEDRawData_SLinkRocketHeaders_h
0003 
0004 #include "FWCore/Utilities/interface/Exception.h"
0005 
0006 //#include <memory>
0007 #include <span>
0008 
0009 /*
0010  * DTH Orbit header, event fragment trailer and SlinkRocket Header and Trailer accompanying
0011  * slink payload. Format that is sent is is low-endian for multi-byte fields
0012  *
0013  * Version 1 DTH and Version 3 SLinkRocket
0014  *
0015  * */
0016 
0017 constexpr uint32_t SLR_MAX_EVENT_LEN = (1 << 20) - 1;
0018 constexpr uint32_t SLR_WORD_NUM_BYTES_SHIFT = 4;
0019 
0020 //SLinkExpress classes
0021 
0022 //begin and end event markers
0023 constexpr uint8_t SLR_BOE = 0x55;
0024 constexpr uint8_t SLR_EOE = 0xaa;
0025 
0026 //minimal SLinkRocket version overlay
0027 class SLinkRocketHeader_version {
0028 public:
0029   SLinkRocketHeader_version() {}
0030   uint8_t version() const { return version_; }
0031   bool verifyMarker() const { return boe_ == SLR_BOE; }
0032 
0033 private:
0034   uint32_t source_id_;
0035   uint16_t l1a_types_;
0036   uint8_t phys_type_;
0037   uint8_t emu_status_ : 2, res1_ : 6;
0038   uint64_t event_id_ : 44, res2_ : 8, version_ : 4, boe_ : 8;
0039 };
0040 
0041 class SLinkRocketHeader_v3 {
0042 public:
0043   SLinkRocketHeader_v3(uint32_t source_id, uint16_t l1a_types, uint8_t l1a_phys, uint8_t emu_status, uint64_t event_id)
0044       : source_id_(source_id),
0045         l1a_types_(l1a_types),
0046         phys_type_(l1a_phys),
0047         emu_status_(emu_status),
0048         event_id_(event_id) {}
0049 
0050   uint32_t sourceID() const { return source_id_; }
0051   uint16_t l1aTypes() const { return l1a_types_; }
0052   uint8_t l1aPhysType() const { return phys_type_; }
0053   uint8_t emuStatus() const { return emu_status_; }
0054   uint64_t globalEventID() const { return event_id_; }
0055   uint8_t version() const { return version_; }
0056   bool verifyMarker() const { return boe_ == SLR_BOE; }
0057 
0058 private:
0059   uint32_t source_id_;
0060   uint16_t l1a_types_;
0061   uint8_t phys_type_;
0062   uint8_t emu_status_ : 2, res1_ : 6;
0063   uint64_t event_id_ : 44, res2_ : 8, version_ : 4 = 3, boe_ : 8 = SLR_BOE;
0064 };
0065 
0066 class SLinkRocketTrailer_v3 {
0067 public:
0068   SLinkRocketTrailer_v3(
0069       uint16_t status, uint16_t crc, uint32_t orbit_id, uint16_t bx_id, uint32_t evtlen_word_count, uint16_t daq_crc)
0070       : crc_(crc), orbit_id_(orbit_id), bx_id_(bx_id), event_length_wcount_(evtlen_word_count), daq_crc_(daq_crc) {
0071     status_.all_ = status;
0072   }
0073 
0074   uint16_t status() const { return status_.all_; }
0075   uint16_t crc() const { return crc_; }
0076   uint32_t orbitID() const { return orbit_id_; }
0077   uint16_t bxID() const { return bx_id_; }
0078   uint32_t eventLenBytes() const { return uint32_t(event_length_wcount_) << SLR_WORD_NUM_BYTES_SHIFT; }
0079   uint16_t daqCRC() const { return daq_crc_; }
0080   bool verifyMarker() const { return eoe_ == SLR_EOE; }
0081 
0082 private:
0083   union {
0084     struct {
0085       uint16_t fed_crc_error_ : 1, /* FED CRC error was detected by DTH and corrected */
0086           slink_crc_error_ : 1, /* Set when the slink receviver finds a mistmatch between calculated crc and daq_crc. It should never happen */
0087           source_id_error_ : 1, /* SOURCE_ID is not expected */
0088           sync_lost_error_ : 1, /* Sync lost detected by DTH */
0089           fragment_cut_ : 1,    /* Fragment was cut */
0090           res_ : 11;
0091     } bits_;
0092     uint16_t all_;
0093   } status_;
0094   uint16_t crc_; /* CRC filled by the FED */
0095   uint32_t orbit_id_;
0096   uint32_t bx_id_ : 12,
0097       event_length_wcount_ : 20; /* Length is encoded in multiples of 128 bits (16 bytes). I.e needs to be shifter by 4 */
0098   uint32_t reserved_ : 8, daq_crc_ : 16, /* CRC filled by the slink sender */
0099       eoe_ : 8 = SLR_EOE;
0100 };
0101 
0102 /*
0103  * version-independent header view parent class
0104  * */
0105 
0106 class SLinkRocketHeaderView {
0107 public:
0108   virtual ~SLinkRocketHeaderView() = default;
0109   virtual uint32_t sourceID() const = 0;
0110   virtual uint16_t l1aTypes() const = 0;
0111   virtual uint8_t l1aPhysType() const = 0;
0112   virtual uint8_t emuStatus() const = 0;
0113   virtual uint64_t globalEventID() const = 0;
0114   virtual uint8_t version() const = 0;
0115   virtual bool verifyMarker() const = 0;
0116 };
0117 
0118 /*
0119  * header v3 view abstraction
0120  * */
0121 
0122 class SLinkRocketHeaderView_v3 : public SLinkRocketHeaderView {
0123 public:
0124   SLinkRocketHeaderView_v3(const void* header) : header_(static_cast<const SLinkRocketHeader_v3*>(header)) {}
0125 
0126   uint32_t sourceID() const override { return header_->sourceID(); }
0127   uint16_t l1aTypes() const override { return header_->l1aTypes(); }
0128   uint8_t l1aPhysType() const override { return header_->l1aPhysType(); }
0129   uint8_t emuStatus() const override { return header_->emuStatus(); }
0130   uint64_t globalEventID() const override { return header_->globalEventID(); }
0131   uint8_t version() const override { return header_->version(); }
0132   bool verifyMarker() const override { return header_->verifyMarker(); }
0133 
0134 private:
0135   const SLinkRocketHeader_v3* header_;
0136 };
0137 
0138 static inline std::unique_ptr<SLinkRocketHeaderView> makeSLinkRocketHeaderView(const void* buf) {
0139   auto version = static_cast<const SLinkRocketHeader_version*>(buf)->version();
0140   if (version == 3)
0141     return std::unique_ptr<SLinkRocketHeaderView>(
0142         static_cast<SLinkRocketHeaderView*>(new SLinkRocketHeaderView_v3(buf)));
0143   throw cms::Exception("SLinkRocketHeaderView::makeView")
0144       << "unknown SLinkRocketHeader version: " << (unsigned int)version;
0145 }
0146 
0147 static inline std::unique_ptr<SLinkRocketHeaderView> makeSLinkRocketHeaderView(std::span<const unsigned char> const& s) {
0148   if (s.size() < sizeof(SLinkRocketHeader_version))
0149     throw cms::Exception("SLinkRocketHeaderView::makeView")
0150         << "size is smaller than SLink header version fields: " << s.size();
0151   auto version = static_cast<const SLinkRocketHeader_version*>(static_cast<const void*>(&s[0]))->version();
0152   if (version == 3 && s.size() != sizeof(SLinkRocketHeader_v3))
0153     throw cms::Exception("SLinkRocketHeaderView::makeView") << "SLinkRocketHeader v3 size mismatch: got " << s.size()
0154                                                             << " expected:" << sizeof(SLinkRocketHeader_v3) << " bytes";
0155 
0156   return makeSLinkRocketHeaderView(static_cast<const void*>(&s[0]));
0157 }
0158 
0159 /*
0160  * version-independent trailer view parent class
0161  * */
0162 
0163 class SLinkRocketTrailerView {
0164 public:
0165   virtual ~SLinkRocketTrailerView() = default;
0166   virtual uint16_t status() const = 0;
0167   virtual uint16_t crc() const = 0;
0168   virtual uint32_t orbitID() const = 0;
0169   virtual uint16_t bxID() const = 0;
0170   virtual uint32_t eventLenBytes() const = 0;
0171   virtual uint16_t daqCRC() const = 0;
0172   virtual bool verifyMarker() const = 0;
0173 };
0174 
0175 /*
0176  * trailer v3 view abstraction
0177  * */
0178 
0179 class SLinkRocketTrailerView_v3 : public SLinkRocketTrailerView {
0180 public:
0181   SLinkRocketTrailerView_v3(const void* trailer) : trailer_(static_cast<const SLinkRocketTrailer_v3*>(trailer)) {}
0182   uint16_t status() const override { return trailer_->status(); }
0183   uint16_t crc() const override { return trailer_->crc(); }
0184   uint32_t orbitID() const override { return trailer_->orbitID(); }
0185   uint16_t bxID() const override { return trailer_->bxID(); }
0186   uint32_t eventLenBytes() const override { return trailer_->eventLenBytes(); }
0187   uint16_t daqCRC() const override { return trailer_->daqCRC(); }
0188   bool verifyMarker() const override { return trailer_->verifyMarker(); }
0189 
0190 private:
0191   const SLinkRocketTrailer_v3* trailer_;
0192 };
0193 
0194 static inline std::unique_ptr<SLinkRocketTrailerView> makeSLinkRocketTrailerView(const void* buf, uint8_t version) {
0195   if (version == 3)
0196     return std::unique_ptr<SLinkRocketTrailerView>(
0197         static_cast<SLinkRocketTrailerView*>(new SLinkRocketTrailerView_v3(buf)));
0198   throw cms::Exception("SLinkRocketTrailerView::makeView")
0199       << "unknown SLinkRocketHeader version: " << (unsigned int)version;
0200 }
0201 
0202 static inline std::unique_ptr<SLinkRocketTrailerView> makeSLinkRocketTrailerView(
0203     std::span<const unsigned char> const& s, uint8_t version) {
0204   if (version == 3 && s.size() < sizeof(SLinkRocketTrailer_v3))
0205     throw cms::Exception("SLinkRocketTrailerView::makeView")
0206         << "SLinkRocketTrailer v3 size mismatch: got " << s.size() << " expected " << sizeof(SLinkRocketTrailer_v3)
0207         << " bytes";
0208   return makeSLinkRocketTrailerView(static_cast<const void*>(&s[0]), version);
0209 }
0210 #endif