CMS 3D CMS Logo

Block.cc
Go to the documentation of this file.
1 #include <iomanip>
2 
4 
6 
7 #define EDM_ML_DEBUG 1
8 
9 namespace l1t {
10 
11  const std::vector<unsigned int> MTF7Payload::block_patterns_ = {
12  // The "0b" prefix indicates binary; the block header id is stored in decimal.
13  // Bits are the left-most bit (D15) of every 16-bit word in the format document.
14  // Bottom-to-top in the document maps to left-to-right in each of the block_patterns_
15  0b000111111111, // Event Record Header : block->header().getID() = 511
16  // Left-most bits of 0xA and 0x9 are both 1 in binary
17  0b0010, // Block of Counters : block->header().getID() = 2
18  0b0011, // ME Data Record : block->header().getID() = 3
19  0b0100, // RPC Data Record : block->header().getID() = 4
20  0b01100101, // SP Output Data Record : block->header().getID() = 101
21  0b11111111 // Event Record Trailer : block->header().getID() = 255
22  // Left-most bits of 0xF and 0xE are both 1 in binary
23  };
24 
25  uint32_t BlockHeader::raw() const {
26  if (type_ == MP7) {
27  LogTrace("L1T") << "Writing MP7 link header";
28  return ((id_ & ID_mask) << ID_shift) | ((size_ & size_mask) << size_shift) |
30  } else if (type_ == CTP7) {
31  LogTrace("L1T") << "Writing CTP7 link header";
32  return flags_;
33  }
34  // if (type_ == MTF7) {
35  // LogTrace("L1T") << "Writing MTF7 link header";
36  // return ((id_ & ID_mask) << ID_shift) | ((size_ & size_mask) << size_shift) | ((capID_ & capID_mask) << capID_shift);
37  // }
38  LogTrace("L1T") << "Writing meaningless link header";
39  return 0;
40  }
41 
42  BxBlocks Block::getBxBlocks(unsigned int payloadWordsPerBx, bool bxHeader) const {
43  BxBlocks bxBlocks;
44 
45  // For MP7 format
46  unsigned int wordsPerBx = payloadWordsPerBx;
47  if (bxHeader) {
48  ++wordsPerBx;
49  }
50  // Calculate how many BxBlock objects can be made with the available payload
51  unsigned int nBxBlocks = payload_.size() / wordsPerBx;
52  for (size_t bxCtr = 0; bxCtr < nBxBlocks; ++bxCtr) {
53  size_t startIdx = bxCtr * wordsPerBx;
54  auto startBxBlock = payload_.cbegin() + startIdx;
55  // Pick the words from the block payload that correspond to the BX and add a BxBlock to the BxBlocks
56  if (bxHeader) {
57  bxBlocks.emplace_back(startBxBlock, startBxBlock + wordsPerBx);
58  } else {
59  bxBlocks.emplace_back(bxCtr, nBxBlocks, startBxBlock, startBxBlock + wordsPerBx);
60  }
61  }
62 
63  return bxBlocks;
64  }
65 
66  std::unique_ptr<Block> Payload::getBlock() {
67  if (end_ - data_ < getHeaderSize()) {
68  LogDebug("L1T") << "Reached end of payload";
69  return std::unique_ptr<Block>();
70  }
71 
72  if (data_[0] == 0xffffffff) {
73  LogDebug("L1T") << "Skipping padding word";
74  ++data_;
75  return getBlock();
76  }
77 
78  auto header = getHeader();
79 
80  if (end_ - data_ < header.getSize()) {
81  edm::LogError("L1T") << "Expecting a block size of " << header.getSize() << " but only " << (end_ - data_)
82  << " words remaining";
83  return std::unique_ptr<Block>();
84  }
85 
86  LogTrace("L1T") << "Creating block with size " << header.getSize();
87 
88  auto res = std::make_unique<Block>(header, data_, data_ + header.getSize());
89  data_ += header.getSize();
90  return res;
91  }
92 
93  MP7Payload::MP7Payload(const uint32_t* data, const uint32_t* end, bool legacy_mc) : Payload(data, end) {
94  // For legacy MC (74 first MC campaigns) skip one empty word that was
95  // reserved for the header. With data, read out infrastructure
96  // version and algorithm version.
97  if (legacy_mc) {
98  LogTrace("L1T") << "Skipping " << std::hex << *data_;
99  ++data_;
100  } else {
101  infra_ = data_[0];
102  algo_ = data_[1];
103  data_ += 2;
104  }
105  }
106 
108  LogTrace("L1T") << "Getting header from " << std::hex << std::setw(8) << *data_;
109 
110  return BlockHeader(data_++);
111  }
112 
113  MTF7Payload::MTF7Payload(const uint32_t* data, const uint32_t* end) : Payload(data, end) {
114  const uint16_t* data16 = reinterpret_cast<const uint16_t*>(data);
115  const uint16_t* end16 = reinterpret_cast<const uint16_t*>(end);
116 
117  if (end16 - data16 < header_size + counter_size + trailer_size) {
118  edm::LogError("L1T") << "MTF7 payload smaller than allowed!";
119  data_ = end_;
120  } else if ( // Check bits for EMTF Event Record Header
121  ((data16[0] >> 12) != 0x9) || ((data16[1] >> 12) != 0x9) || ((data16[2] >> 12) != 0x9) ||
122  ((data16[3] >> 12) != 0x9) || ((data16[4] >> 12) != 0xA) || ((data16[5] >> 12) != 0xA) ||
123  ((data16[6] >> 12) != 0xA) || ((data16[7] >> 12) != 0xA) || ((data16[8] >> 15) != 0x1) ||
124  ((data16[9] >> 15) != 0x0) || ((data16[10] >> 15) != 0x0) || ((data16[11] >> 15) != 0x0)) {
125  edm::LogError("L1T") << "MTF7 payload has invalid header!";
126  data_ = end_;
127  } else if ( // Check bits for EMTF MPC Link Errors
128  ((data16[12] >> 15) != 0) || ((data16[13] >> 15) != 1) || ((data16[14] >> 15) != 0) ||
129  ((data16[15] >> 15) != 0)) {
130  edm::LogError("L1T") << "MTF7 payload has invalid counter block!";
131  data_ = end_;
132  }
133 
134  // Check bits for EMTF Event Record Trailer, get firmware version
135  algo_ = 0; // Firmware version
136  for (int i = 4; i < 1590; i++) { // Start after Counters block, up to 108 ME / 84 RPC / 3 SP blocks per BX, 8 BX
137  if (((data16[4 * i + 0] >> 12) == 0xF) && ((data16[4 * i + 1] >> 12) == 0xF) &&
138  ((data16[4 * i + 2] >> 12) == 0xF) && ((data16[4 * i + 3] >> 12) == 0xF) &&
139  ((data16[4 * i + 4] >> 12) == 0xE) && ((data16[4 * i + 5] >> 12) == 0xE) &&
140  ((data16[4 * i + 6] >> 12) == 0xE) &&
141  ((data16[4 * i + 7] >> 12) == 0xE)) { // Indicators for the Trailer block
142  algo_ = (((data16[4 * i + 2] >> 4) & 0x3F) << 9); // Year (6 bits)
143  algo_ |= (((data16[4 * i + 2] >> 0) & 0x0F) << 5); // Month (4 bits)
144  algo_ |= (((data16[4 * i + 4] >> 0) & 0x1F) << 0); // Day (5 bits)
145  break;
146  }
147  }
148  if (algo_ == 0) {
149  edm::LogError("L1T") << "MTF7 payload has no valid EMTF firmware version!";
150  data_ = end_;
151  }
152  }
153 
154  int MTF7Payload::count(unsigned int pattern, unsigned int length) const {
155  unsigned int mask = 0;
156  for (; length > 0; length--)
157  mask = (mask << 4) | 0xf;
158 
159  int count = 0;
160  for (const auto& p : block_patterns_)
161  count += (p & mask) == pattern;
162  return count;
163  }
164 
165  bool MTF7Payload::valid(unsigned int pattern) const {
166  for (const auto& p : block_patterns_) {
167  if (p == pattern)
168  return true;
169  }
170  return false;
171  }
172 
173  std::unique_ptr<Block> MTF7Payload::getBlock() {
174  if (end_ - data_ < 2)
175  return std::unique_ptr<Block>();
176 
177  const uint16_t* data16 = reinterpret_cast<const uint16_t*>(data_);
178  const uint16_t* end16 = reinterpret_cast<const uint16_t*>(end_);
179 
180  // Read in blocks equivalent to 64 bit words, trying to match the
181  // pattern of first bits to what is deemed valid.
182  std::vector<uint32_t> payload;
183  unsigned int pattern = 0;
184  unsigned int i = 0;
185  for (; i < max_block_length_ and data16 + (i + 1) * 4 <= end16; ++i) {
186  for (int j = 0; j < 4; ++j) {
187  auto n = i * 4 + j;
188  pattern |= (data16[n] >> 15) << n;
189  payload.push_back(data16[n]);
190  }
191 
192  if (count(pattern, i + 1) == 1 and valid(pattern))
193  break;
194  }
195 
196  if (not valid(pattern)) {
197  edm::LogWarning("L1T") << "MTF7 block with unrecognized id 0x" << std::hex << pattern;
198  return std::unique_ptr<Block>();
199  }
200 
201  data_ += (i + 1) * 2;
202  return std::make_unique<Block>(pattern, payload, 0, MTF7);
203  }
204 
205  CTP7Payload::CTP7Payload(const uint32_t* data, const uint32_t* end, amc::Header amcHeader)
206  : Payload(data, end), amcHeader_(amcHeader) {
207  if (not(*data_ == 0xA110CA7E)) {
208  edm::LogError("L1T") << "CTP7 block with invalid header:" << std::hex << *data_;
209  }
210  ++data_;
211  bx_per_l1a_ = (*data_ >> 16) & 0xff;
212  calo_bxid_ = *data_ & 0xfff;
213  capId_ = 0;
214  if (bx_per_l1a_ > 1) {
215  edm::LogInfo("L1T") << "CTP7 block with multiple bunch crossings:" << bx_per_l1a_;
216  }
218  infra_ = 0;
219  ++data_;
220  }
221 
223  // only one block type, use dummy id
224  unsigned blockId = 0;
225  // CTP7 header contains number of BX in payload and the bunch crossing ID
226  // Not sure how to map to generic BlockHeader variables, so just packing
227  // it all in flags variable
228  unsigned blockFlags = ((bx_per_l1a_ & 0xf) << 16) | (calo_bxid_ & 0xfff);
229  unsigned blockSize = 192;
230  return BlockHeader(blockId, blockSize, capId_, blockFlags, CTP7);
231  }
232 
233  std::unique_ptr<Block> CTP7Payload::getBlock() {
234  if (end_ - data_ < getHeaderSize()) {
235  LogDebug("L1T") << "Reached end of payload";
236  return std::unique_ptr<Block>();
237  }
238  if (capId_ > bx_per_l1a_) {
239  edm::LogWarning("L1T") << "CTP7 with more bunch crossings than expected";
240  }
241 
242  auto header = getHeader();
243 
244  if (end_ - data_ < header.getSize()) {
245  edm::LogError("L1T") << "Expecting a block size of " << header.getSize() << " but only " << (end_ - data_)
246  << " words remaining";
247  return std::unique_ptr<Block>();
248  }
249 
250  LogTrace("L1T") << "Creating block with size " << header.getSize();
251 
252  auto res = std::make_unique<Block>(header, data_, data_ + header.getSize());
253  data_ += header.getSize();
254  capId_++;
255  return res;
256  }
257 } // namespace l1t
#define LogDebug(id)
BlockHeader getHeader() override
Definition: Block.cc:222
static constexpr unsigned capID_shift
Definition: Block.h:42
MP7Payload(const uint32_t *data, const uint32_t *end, bool legacy_mc=false)
Definition: Block.cc:93
Definition: Block.h:11
static constexpr unsigned capID_mask
Definition: Block.h:43
static constexpr unsigned flags_mask
Definition: Block.h:45
static constexpr unsigned size_shift
Definition: Block.h:40
static constexpr unsigned max_block_length_
Definition: Block.h:129
unsigned getHeaderSize() const override
Definition: Block.h:139
static constexpr unsigned flags_shift
Definition: Block.h:44
static constexpr unsigned header_size
Definition: Block.h:123
delete x;
Definition: CaloConfig.h:22
int count(unsigned int pattern, unsigned int length) const
Definition: Block.cc:154
block_t type_
Definition: Block.h:51
const uint32_t * end_
Definition: Block.h:100
unsigned int flags_
Definition: Block.h:50
virtual std::unique_ptr< Block > getBlock()
Definition: Block.cc:66
Definition: Electron.h:6
unsigned capId_
Definition: Block.h:149
static constexpr unsigned counter_size
Definition: Block.h:124
bool valid(unsigned int pattern) const
Definition: Block.cc:165
static constexpr unsigned ID_mask
Definition: Block.h:39
#define end
Definition: vmac.h:39
unsigned infra_
Definition: Block.h:103
unsigned int size_
Definition: Block.h:48
#define LogTrace(id)
MTF7Payload(const uint32_t *data, const uint32_t *end)
Definition: Block.cc:113
unsigned int capID_
Definition: Block.h:49
const uint32_t * data_
Definition: Block.h:99
static constexpr unsigned size_mask
Definition: Block.h:41
std::vector< BxBlock > BxBlocks
Definition: BxBlock.h:79
unsigned calo_bxid_
Definition: Block.h:151
CTP7Payload(const uint32_t *data, const uint32_t *end, amc::Header amcHeader)
Definition: Block.cc:205
BlockHeader getHeader() override
Definition: Block.cc:107
static constexpr unsigned trailer_size
Definition: Block.h:125
unsigned int getUserData() const
Definition: AMCSpec.h:77
unsigned bx_per_l1a_
Definition: Block.h:150
BxBlocks getBxBlocks(unsigned int payloadWordsPerBx, bool bxHeader) const
Definition: Block.cc:42
char data[epos_bytes_allocation]
Definition: EPOS_Wrapper.h:79
unsigned int id_
Definition: Block.h:47
std::unique_ptr< Block > getBlock() override
Definition: Block.cc:233
static constexpr unsigned ID_shift
Definition: Block.h:38
amc::Header amcHeader_
Definition: Block.h:152
uint32_t raw() const
Definition: Block.cc:25
unsigned algo_
Definition: Block.h:102
static const std::vector< unsigned int > block_patterns_
Definition: Block.h:130
std::unique_ptr< Block > getBlock() override
Definition: Block.cc:173