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