Block

BlockHeader

CTP7Payload

MP7Payload

MTF7Payload

Payload

block_t

mtf7_block_t

Macros

Line Code
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195
#ifndef EventFilter_L1TRawToDigi_Block_h
#define EventFilter_L1TRawToDigi_Block_h

#include <memory>
#include <vector>
#include <optional>

#include "EventFilter/L1TRawToDigi/interface/AMCSpec.h"
#include "DataFormats/L1Trigger/interface/BxBlock.h"

namespace l1t {
  enum block_t { MP7 = 0, CTP7, MTF7 };
  namespace mtf7 {
    enum mtf7_block_t {
      // The "0b" prefix indicates binary; the block header id is stored in decimal.
      // Bits are the left-most bit (D15) of every 16-bit word in the format document.
      // Bottom-to-top in the document maps to left-to-right in each of the bit pattern.
      EvHd = 0b000111111111,  ///< Event Record Header   : block->header().getID() = 511
      CnBlk = 0b0010,         ///< Block of Counters     : block->header().getID() = 2
      ME = 0b0011,            ///< ME Data Record        : block->header().getID() = 3
      RPC = 0b0100,           ///< RPC Data Record       : block->header().getID() = 4
      GEM = 0b0111,           ///< GEM Data Record       : block->header().getID() = 7
      // FIXME, not currently defined... guess? JS - 01.07.20
      ME0 = 0b0110,        ///< ME0 Data Record       : block->header().getID() = 6
      SPOut = 0b01100101,  ///< SP Output Data Record : block->header().getID() = 101
      EvTr = 0b11111111    ///< Event Record Trailer  : block->header().getID() = 255
    };
  }

  class BlockHeader {
  public:
    BlockHeader(unsigned int id, unsigned int size, unsigned int capID = 0, unsigned int flags = 0, block_t type = MP7)
        : id_(id), size_(size), capID_(capID), flags_(flags), type_(type) {}
    // Create a MP7 block header: everything is contained in the raw uint32
    BlockHeader(const uint32_t* data)
        : id_((data[0] >> ID_shift) & ID_mask),
          size_((data[0] >> size_shift) & size_mask),
          capID_((data[0] >> capID_shift) & capID_mask),
          flags_((data[0] >> flags_shift) & flags_mask),
          type_(MP7) {}

    bool operator<(const BlockHeader& o) const { return getID() < o.getID(); };

    unsigned int getID() const { return id_; };
    unsigned int getSize() const { return size_; };
    unsigned int getCapID() const { return capID_; };
    unsigned int getFlags() const { return flags_; };
    block_t getType() const { return type_; };

    uint32_t raw() const;

  private:
    static constexpr unsigned CTP7_shift = 0;
    static constexpr unsigned CTP7_mask = 0xffff;
    static constexpr unsigned ID_shift = 24;
    static constexpr unsigned ID_mask = 0xff;
    static constexpr unsigned size_shift = 16;
    static constexpr unsigned size_mask = 0xff;
    static constexpr unsigned capID_shift = 8;
    static constexpr unsigned capID_mask = 0xff;
    static constexpr unsigned flags_shift = 0;
    static constexpr unsigned flags_mask = 0xff;

    unsigned int id_;
    unsigned int size_;
    unsigned int capID_;
    unsigned int flags_;
    block_t type_;
  };

  class Block {
  public:
    Block(const BlockHeader& h, const uint32_t* payload_start, const uint32_t* payload_end)
        : header_(h), payload_(payload_start, payload_end) {}
    Block(unsigned int id,
          const std::vector<uint32_t>& payload,
          unsigned int capID = 0,
          unsigned int flags = 0,
          block_t type = MP7)
        : header_(id, payload.size(), capID, flags, type), payload_(payload) {}

    bool operator<(const Block& o) const { return header() < o.header(); };

    inline unsigned int getSize() const { return payload_.size() + 1; };

    BlockHeader header() const { return header_; };
    const std::vector<uint32_t>& payload() const { return payload_; };

    void amc(const amc::Header& h) { amc_ = h; };
    amc::Header amc() const { return amc_; };

    BxBlocks getBxBlocks(unsigned int payloadWordsPerBx, bool bxHeader) const;

  private:
    BlockHeader header_;
    amc::Header amc_;
    std::vector<uint32_t> payload_;
  };

  typedef std::vector<Block> Blocks;

  class Payload {
  public:
    Payload(const uint32_t* data, const uint32_t* end) : data_(data), end_(end), algo_(0), infra_(0) {}
    virtual ~Payload() {}
    virtual unsigned getAlgorithmFWVersion() const { return algo_; };
    virtual unsigned getInfrastructureFWVersion() const { return infra_; };
    virtual unsigned getHeaderSize() const = 0;
    // Read header from data_ and advance data_ to point behind the
    // header.  Called by getBlock(), which also checks that data_ !=
    // end_ before calling (assumes size of one 32 bit word).
    virtual BlockHeader getHeader() = 0;
    virtual std::optional<Block> getBlock();

  protected:
    const uint32_t* data_;
    const uint32_t* end_;

    unsigned algo_;
    unsigned infra_;
  };

  class MP7Payload : public Payload {
  public:
    MP7Payload(const uint32_t* data, const uint32_t* end, bool legacy_mc = false);
    unsigned getHeaderSize() const override { return 1; };
    BlockHeader getHeader() override;
  };

  class MTF7Payload : public Payload {
  public:
    MTF7Payload(const uint32_t* data, const uint32_t* end);
    // Unused methods - we override getBlock() instead
    unsigned getHeaderSize() const override { return 0; };
    BlockHeader getHeader() override { return BlockHeader(nullptr); };
    std::optional<Block> getBlock() override;

  private:
    // sizes in 16 bit words
    static constexpr unsigned header_size = 12;
    static constexpr unsigned counter_size = 4;
    static constexpr unsigned trailer_size = 8;

    /// Start of the EMTF DAQ payload, in number of 64-bit words
    static constexpr unsigned DAQ_PAYLOAD_OFFSET = 4;
    /// Maximum number of BX per MTF7 payload
    static constexpr unsigned MAX_BX_PER_PAYLOAD = 8;
    /// Maximum number of CSC words per MTF7 payload per bx: 9 links/sectors, 6 stations, 2 LCTs
    static constexpr unsigned ME_MAX_PER_BX = 108;
    /// Maximum number of RPC words per MTF7 payload per bx: 7 links/sectors, 6 stations, 2 segments
    static constexpr unsigned RPC_MAX_PER_BX = 84;
    /// Maximum number of GE1/1 words per MTF7 payload per bx: 7 GE1/1 links, 2 layers, 8 clusters
    static constexpr unsigned GE11_MAX_PER_BX = 112;
    /// TODO: Maximum number of GE2/1 words per MTF7 payload per bx: ?? GE2/1 links, 2 layers, ?? clusters
    static constexpr unsigned GE21_MAX_PER_BX = 0;
    /// TODO: Maximum number of ME0 words per MTF7 payload per bx: ?? ME0 links, ?? layers, ?? clusters
    static constexpr unsigned ME0_MAX_PER_BX = 0;
    /// Maximum number of SPz words per MTF7 payload per bx: 3 tracks, 2 words per track
    static constexpr unsigned SP_MAX_PER_BX = 6;
    /// Maximum number of 64-bit words in the EMTF payload
    static constexpr unsigned PAYLOAD_MAX_SIZE =
        MAX_BX_PER_PAYLOAD *
            (ME_MAX_PER_BX + RPC_MAX_PER_BX + GE11_MAX_PER_BX + GE21_MAX_PER_BX + ME0_MAX_PER_BX + SP_MAX_PER_BX) +
        (trailer_size / 4);

    static constexpr unsigned max_block_length_ = 3;         ///< maximum of the block length (64bits)
    static const std::vector<unsigned int> block_patterns_;  ///< bit patterns of the first bits (of 16bit words)

    int count(unsigned int pattern, unsigned int length) const;
    bool valid(unsigned int pattern) const;
  };

  class CTP7Payload : public Payload {
  public:
    CTP7Payload(const uint32_t* data, const uint32_t* end, amc::Header amcHeader);
    unsigned getHeaderSize() const override { return 2; };
    BlockHeader getHeader() override;
    std::optional<Block> getBlock() override;

  private:
    // FIXME check values
    static constexpr unsigned size_mask = 0xff;
    static constexpr unsigned size_shift = 16;

    unsigned size_;
    unsigned capId_;
    unsigned bx_per_l1a_;
    unsigned calo_bxid_;
    unsigned six_hcal_feature_bits_;
    unsigned slot7_card_;
    amc::Header amcHeader_;
  };
}  // namespace l1t

#endif