CMS 3D CMS Logo

SiStripRawToDigiUnpacker.cc
Go to the documentation of this file.
15 #include <iostream>
16 #include <sstream>
17 #include <iomanip>
18 #include <boost/format.hpp>
19 #include <ext/algorithm>
21 
22 namespace sistrip {
23 
24  RawToDigiUnpacker::RawToDigiUnpacker(int16_t appended_bytes,
25  int16_t fed_buffer_dump_freq,
26  int16_t fed_event_dump_freq,
27  int16_t trigger_fed_id,
28  bool using_fed_key,
29  bool unpack_bad_channels,
30  bool mark_missing_feds,
31  const uint32_t errorThreshold)
32  : headerBytes_(appended_bytes),
33  fedBufferDumpFreq_(fed_buffer_dump_freq),
34  fedEventDumpFreq_(fed_event_dump_freq),
35  triggerFedId_(trigger_fed_id),
36  useFedKey_(using_fed_key),
37  unpackBadChannels_(unpack_bad_channels),
38  markMissingFeds_(mark_missing_feds),
39  event_(0),
40  once_(true),
41  first_(true),
42  useDaqRegister_(false),
43  quiet_(true),
44  extractCm_(false),
45  doFullCorruptBufferChecks_(false),
46  doAPVEmulatorCheck_(true),
47  errorThreshold_(errorThreshold),
48  warnings_(sistrip::mlRawToDigi_, "[sistrip::RawToDigiUnpacker::createDigis]", edm::isDebugEnabled()) {
49  if (edm::isDebugEnabled()) {
50  LogTrace("SiStripRawToDigi") << "[sistrip::RawToDigiUnpacker::" << __func__ << "]"
51  << " Constructing object...";
52  }
53  if (unpackBadChannels_) {
54  edm::LogWarning("SiStripRawToDigi")
55  << "Warning: Unpacking of bad channels enabled. Only enable this if you know what you are doing. "
56  << std::endl;
57  }
58  }
59 
61  if (edm::isDebugEnabled()) {
62  LogTrace("SiStripRawToDigi") << "[sistrip::RawToDigiUnpacker::" << __func__ << "]"
63  << " Destructing object...";
64  }
65  }
66 
67  namespace {
68 
69  edm::RunningAverage localRA(10000);
70 
71  }
72 
74  const FEDRawDataCollection& buffers,
76  RawDigis& scope_mode,
77  RawDigis& virgin_raw,
78  RawDigis& proc_raw,
79  Digis& zero_suppr,
80  DetIdCollection& detids,
81  RawDigis& cm_values) {
82  // Clear done at the end
83  assert(zs_work_digis_.empty());
84  zs_work_digis_.reserve(localRA.upper());
85  // Reserve space in bad module list
86  detids.reserve(100);
87 
88  // Check if FEDs found in cabling map and event data
89  if (cabling.fedIds().empty()) {
90  warnings_.add("No FEDs found in cabling map!");
91  if (edm::isDebugEnabled()) {
92  // Check which FED ids have non-zero size buffers
93  std::vector<uint16_t> feds;
94  for (uint16_t ifed = FEDNumbering::MINSiStripFEDID; ifed < FEDNumbering::MAXSiStripFEDID; ifed++) {
95  if (ifed != triggerFedId_ && buffers.FEDData(static_cast<int>(ifed)).size()) {
96  feds.push_back(ifed);
97  }
98  }
99  LogTrace("SiStripRawToDigi") << "[sistrip::RawToDigiUnpacker::" << __func__ << "]"
100  << " Found " << feds.size() << " FED buffers with non-zero size!";
101  }
102  }
103 
104  // Flag for EventSummary update using DAQ register
105  bool first_fed = true;
106 
107  // Retrieve FED ids from cabling map and iterate through
108  std::vector<uint16_t>::const_iterator ifed = cabling.fedIds().begin();
109  for (; ifed != cabling.fedIds().end(); ifed++) {
110  // ignore trigger FED
111  if (*ifed == triggerFedId_) {
112  continue;
113  }
114 
115  // Retrieve FED raw data for given FED
116  const FEDRawData& input = buffers.FEDData(static_cast<int>(*ifed));
117 
118  // Some debug on FED buffer size
119  if (edm::isDebugEnabled()) {
120  if (first_ && input.data()) {
121  std::stringstream ss;
122  ss << "[sistrip::RawToDigiUnpacker::" << __func__ << "]"
123  << " Found FED id " << std::setw(4) << std::setfill(' ') << *ifed << " in FEDRawDataCollection"
124  << " with non-zero pointer 0x" << std::hex << std::setw(8) << std::setfill('0')
125  << reinterpret_cast<uint32_t*>(const_cast<uint8_t*>(input.data())) << std::dec << " and size "
126  << std::setw(5) << std::setfill(' ') << input.size() << " chars";
127  LogTrace("SiStripRawToDigi") << ss.str();
128  }
129  }
130 
131  // Dump of FEDRawData to stdout
132  if (edm::isDebugEnabled()) {
134  std::stringstream ss;
135  dumpRawData(*ifed, input, ss);
137  }
138  }
139 
140  // get the cabling connections for this FED
141  auto conns = cabling.fedConnections(*ifed);
142 
143  // Check on FEDRawData pointer
144  if (!input.data()) {
145  warnings_.add("NULL pointer to FEDRawData for FED", (boost::format("id %1%") % *ifed).str());
146  // Mark FED modules as bad
147  detids.reserve(detids.size() + conns.size());
148  std::vector<FedChannelConnection>::const_iterator iconn = conns.begin();
149  for (; iconn != conns.end(); iconn++) {
150  if (!iconn->detId() || iconn->detId() == sistrip::invalid32_)
151  continue;
152  detids.push_back(iconn->detId()); //@@ Possible multiple entries (ok for Giovanni)
153  }
154  continue;
155  }
156 
157  // Check on FEDRawData size
158  if (!input.size()) {
159  warnings_.add("FEDRawData has zero size for FED", (boost::format("id %1%") % *ifed).str());
160  // Mark FED modules as bad
161  detids.reserve(detids.size() + conns.size());
162  std::vector<FedChannelConnection>::const_iterator iconn = conns.begin();
163  for (; iconn != conns.end(); iconn++) {
164  if (!iconn->detId() || iconn->detId() == sistrip::invalid32_)
165  continue;
166  detids.push_back(iconn->detId()); //@@ Possible multiple entries (ok for Giovanni)
167  }
168  continue;
169  }
170 
171  // construct FEDBuffer
172  std::unique_ptr<sistrip::FEDBuffer> buffer;
173  try {
174  buffer.reset(new sistrip::FEDBuffer(input.data(), input.size()));
175  buffer->setLegacyMode(legacy_);
176  if (!buffer->doChecks(true)) {
177  if (!unpackBadChannels_ || !buffer->checkNoFEOverflows())
178  throw cms::Exception("FEDBuffer") << "FED Buffer check fails for FED ID " << *ifed << ".";
179  }
180  if (doFullCorruptBufferChecks_ && !buffer->doCorruptBufferChecks()) {
181  throw cms::Exception("FEDBuffer") << "FED corrupt buffer check fails for FED ID " << *ifed << ".";
182  }
183  } catch (const cms::Exception& e) {
184  warnings_.add("Exception caught when creating FEDBuffer object for FED",
185  (boost::format("id %1%: %2%") % *ifed % e.what()).str());
186  // FED buffer is bad and should not be unpacked. Skip this FED and mark all modules as bad.
187  std::vector<FedChannelConnection>::const_iterator iconn = conns.begin();
188  for (; iconn != conns.end(); iconn++) {
189  if (!iconn->detId() || iconn->detId() == sistrip::invalid32_)
190  continue;
191  detids.push_back(iconn->detId()); //@@ Possible multiple entries (ok for Giovanni)
192  }
193  continue;
194  }
195 
196  // Check if EventSummary ("trigger FED info") needs updating
197  if (first_fed && useDaqRegister_) {
198  updateEventSummary(*buffer, summary);
199  first_fed = false;
200  }
201 
202  // Check to see if EventSummary info is set
203  if (!quiet_ && !summary.isSet()) {
204  warnings_.add(
205  "EventSummary is not set correctly! Missing information from both \"trigger FED\" and \"DAQ registers\"!");
206  }
207 
208  // Check to see if event is to be analyzed according to EventSummary
209  if (!summary.valid()) {
210  if (edm::isDebugEnabled()) {
211  LogTrace("SiStripRawToDigi") << "[sistrip::RawToDigiUnpacker::" << __func__ << "]"
212  << " EventSummary is not valid: skipping...";
213  }
214  continue;
215  }
216 
218  sistrip::FEDReadoutMode mode = buffer->readoutMode();
220  (legacy_) ? buffer->legacyReadoutMode() : sistrip::READOUT_MODE_LEGACY_INVALID;
221 
222  // Retrive run type
223  sistrip::RunType runType_ = summary.runType();
224  if (runType_ == sistrip::APV_LATENCY || runType_ == sistrip::FINE_DELAY) {
225  useFedKey_ = false;
226  }
227 
228  // Dump of FED buffer
229  if (edm::isDebugEnabled()) {
231  std::stringstream ss;
232  buffer->dump(ss);
234  }
235  }
236 
237  // Iterate through FED channels, extract payload and create Digis
238  std::vector<FedChannelConnection>::const_iterator iconn = conns.begin();
239  for (; iconn != conns.end(); iconn++) {
241  uint16_t chan = iconn->fedCh();
242 
243  // Check if fed connection is valid
244  if (!iconn->isConnected()) {
245  continue;
246  }
247 
248  // Check DetId is valid (if to be used as key)
249  if (!useFedKey_ && (!iconn->detId() || iconn->detId() == sistrip::invalid32_)) {
250  continue;
251  }
252 
253  // Check FED channel
254  if (!buffer->channelGood(iconn->fedCh(), doAPVEmulatorCheck_)) {
255  if (!unpackBadChannels_ || !(buffer->fePresent(iconn->fedCh() / FEDCH_PER_FEUNIT) &&
256  buffer->feEnabled(iconn->fedCh() / FEDCH_PER_FEUNIT))) {
257  detids.push_back(iconn->detId()); //@@ Possible multiple entries (ok for Giovanni)
258  continue;
259  }
260  }
261 
262  // Determine whether FED key is inferred from cabling or channel loop
263  uint32_t fed_key = (summary.runType() == sistrip::FED_CABLING)
264  ? ((*ifed & sistrip::invalid_) << 16) | (chan & sistrip::invalid_)
265  : ((iconn->fedId() & sistrip::invalid_) << 16) | (iconn->fedCh() & sistrip::invalid_);
266 
267  // Determine whether DetId or FED key should be used to index digi containers
268  uint32_t key = (useFedKey_ || (!legacy_ && mode == sistrip::READOUT_MODE_SCOPE) ||
270  ? fed_key
271  : iconn->detId();
272 
273  // Determine APV std::pair number (needed only when using DetId)
274  uint16_t ipair = (useFedKey_ || (!legacy_ && mode == sistrip::READOUT_MODE_SCOPE) ||
276  ? 0
277  : iconn->apvPairNumber();
278 
279  if ((!legacy_ &&
283  Registry regItem(key, 0, zs_work_digis_.size(), 0);
284 
285  try {
288  const uint8_t packet_code = buffer->packetCode(legacy_, iconn->fedCh());
289  switch (packet_code) {
292  sistrip::FEDZSChannelUnpacker::zeroSuppressedModeUnpacker(buffer->channel(iconn->fedCh()));
293  while (unpacker.hasData()) {
294  zs_work_digis_.push_back(SiStripDigi(unpacker.sampleNumber() + ipair * 256, unpacker.adc()));
295  unpacker++;
296  }
297  break;
298  }
301  sistrip::FEDBSChannelUnpacker::zeroSuppressedModeUnpacker(buffer->channel(iconn->fedCh()), 10);
302  while (unpacker.hasData()) {
303  zs_work_digis_.push_back(SiStripDigi(unpacker.sampleNumber() + ipair * 256, unpacker.adc()));
304  unpacker++;
305  }
306  break;
307  }
310  sistrip::FEDBSChannelUnpacker::zeroSuppressedModeUnpacker(buffer->channel(iconn->fedCh()), 8);
311  while (unpacker.hasData()) {
312  zs_work_digis_.push_back(SiStripDigi(unpacker.sampleNumber() + ipair * 256, unpacker.adc() << 2));
313  unpacker++;
314  }
315  break;
316  }
319  sistrip::FEDBSChannelUnpacker::zeroSuppressedModeUnpacker(buffer->channel(iconn->fedCh()), 8);
320  while (unpacker.hasData()) {
321  zs_work_digis_.push_back(SiStripDigi(unpacker.sampleNumber() + ipair * 256, unpacker.adc() << 1));
322  unpacker++;
323  }
324  break;
325  }
326  default: {
327  warnings_.add((boost::format("Invalid packet code %1$#x for zero-suppressed data") %
328  uint16_t(buffer->packetCode(legacy_, iconn->fedCh())))
329  .str(),
330  (boost::format("FED %1% channel %2%") % *ifed % iconn->fedCh()).str());
331  if (packet_code == 0) {
332  // workaround for a pre-2015 bug in the packer: assume default ZS packing
334  sistrip::FEDZSChannelUnpacker::zeroSuppressedModeUnpacker(buffer->channel(iconn->fedCh()));
335  while (unpacker.hasData()) {
336  zs_work_digis_.push_back(SiStripDigi(unpacker.sampleNumber() + ipair * 256, unpacker.adc()));
337  unpacker++;
338  }
339  }
340  }
341  }
342  } catch (const cms::Exception& e) {
343  warnings_.add("Clusters are not ordered",
344  (boost::format("FED %1% channel %2% : %3%") % *ifed % iconn->fedCh() % e.what()).str());
345  detids.push_back(iconn->detId()); //@@ Possible multiple entries (ok for Giovanni)
346  continue;
347  }
348 
349  regItem.length = zs_work_digis_.size() - regItem.index;
350  if (regItem.length > 0) {
351  regItem.first = zs_work_digis_[regItem.index].strip();
352  zs_work_registry_.push_back(regItem);
353  }
354 
355  // Common mode values
356  if (extractCm_) {
357  try {
358  Registry regItem2(key, 2 * ipair, cm_work_digis_.size(), 2);
359  cm_work_digis_.push_back(SiStripRawDigi(buffer->channel(iconn->fedCh()).cmMedian(0)));
360  cm_work_digis_.push_back(SiStripRawDigi(buffer->channel(iconn->fedCh()).cmMedian(1)));
361  cm_work_registry_.push_back(regItem2);
362  } catch (const cms::Exception& e) {
363  warnings_.add("Problem extracting common modes",
364  (boost::format("FED %1% channel %2%:\n %3%") % *ifed % iconn->fedCh() % e.what()).str());
365  }
366  }
367 
368  }
369 
372  Registry regItem(key, 0, zs_work_digis_.size(), 0);
373 
374  try {
377  sistrip::FEDBSChannelUnpacker::zeroSuppressedLiteModeUnpacker(buffer->channel(iconn->fedCh()), 10);
378 
380  while (unpacker.hasData()) {
381  zs_work_digis_.push_back(SiStripDigi(unpacker.sampleNumber() + ipair * 256, unpacker.adc()));
382  unpacker++;
383  }
384  } catch (const cms::Exception& e) {
385  warnings_.add("Clusters are not ordered",
386  (boost::format("FED %1% channel %2%: %3%") % *ifed % iconn->fedCh() % e.what()).str());
387  detids.push_back(iconn->detId()); //@@ Possible multiple entries (ok for Giovanni)
388  continue;
389  }
390 
391  regItem.length = zs_work_digis_.size() - regItem.index;
392  if (regItem.length > 0) {
393  regItem.first = zs_work_digis_[regItem.index].strip();
394  zs_work_registry_.push_back(regItem);
395  }
396 
397  }
398 
399  else if ((!legacy_ && (mode == sistrip::READOUT_MODE_ZERO_SUPPRESSED_LITE8 ||
407  Registry regItem(key, 0, zs_work_digis_.size(), 0);
408 
409  size_t bits_shift = 0;
412  bits_shift = 1;
415  bits_shift = 2;
416 
417  try {
420  sistrip::FEDZSChannelUnpacker::zeroSuppressedLiteModeUnpacker(buffer->channel(iconn->fedCh()));
421 
423  while (unpacker.hasData()) {
424  zs_work_digis_.push_back(
425  SiStripDigi(unpacker.sampleNumber() + ipair * 256, unpacker.adc() << bits_shift));
426  unpacker++;
427  }
428  } catch (const cms::Exception& e) {
429  warnings_.add("Clusters are not ordered",
430  (boost::format("FED %1% channel %2%: %3%") % *ifed % iconn->fedCh() % e.what()).str());
431  detids.push_back(iconn->detId()); //@@ Possible multiple entries (ok for Giovanni)
432  continue;
433  }
434 
435  regItem.length = zs_work_digis_.size() - regItem.index;
436  if (regItem.length > 0) {
437  regItem.first = zs_work_digis_[regItem.index].strip();
438  zs_work_registry_.push_back(regItem);
439  }
440 
441  }
442 
443  else if ((!legacy_ && mode == sistrip::READOUT_MODE_PREMIX_RAW) ||
445  Registry regItem(key, 0, zs_work_digis_.size(), 0);
446 
447  try {
450  sistrip::FEDZSChannelUnpacker::preMixRawModeUnpacker(buffer->channel(iconn->fedCh()));
451 
453  while (unpacker.hasData()) {
454  zs_work_digis_.push_back(SiStripDigi(unpacker.sampleNumber() + ipair * 256, unpacker.adcPreMix()));
455  unpacker++;
456  }
457  } catch (const cms::Exception& e) {
458  warnings_.add("Clusters are not ordered",
459  (boost::format("FED %1% channel %2%: %3%") % *ifed % iconn->fedCh() % e.what()).str());
460  detids.push_back(iconn->detId()); //@@ Possible multiple entries (ok for Giovanni)
461  continue;
462  }
463 
464  regItem.length = zs_work_digis_.size() - regItem.index;
465  if (regItem.length > 0) {
466  regItem.first = zs_work_digis_[regItem.index].strip();
467  zs_work_registry_.push_back(regItem);
468  }
469 
470  }
471 
472  else if ((!legacy_ && mode == sistrip::READOUT_MODE_VIRGIN_RAW) ||
475  std::vector<uint16_t> samples;
476 
479 
480  uint8_t packet_code = buffer->packetCode(legacy_);
481  if (packet_code == PACKET_CODE_VIRGIN_RAW) {
483  sistrip::FEDRawChannelUnpacker::virginRawModeUnpacker(buffer->channel(iconn->fedCh()));
484  while (unpacker.hasData()) {
485  samples.push_back(unpacker.adc());
486  unpacker++;
487  }
488  } else {
489  if (packet_code == PACKET_CODE_VIRGIN_RAW10) {
491  sistrip::FEDBSChannelUnpacker::virginRawModeUnpacker(buffer->channel(iconn->fedCh()), 10);
492  while (unpacker.hasData()) {
493  samples.push_back(unpacker.adc());
494  unpacker.sampleNumber();
495  unpacker++;
496  }
497  } else if (packet_code == PACKET_CODE_VIRGIN_RAW8_BOTBOT) {
499  sistrip::FEDBSChannelUnpacker::virginRawModeUnpacker(buffer->channel(iconn->fedCh()), 8);
500  while (unpacker.hasData()) {
501  samples.push_back((unpacker.adc() << 2));
502  unpacker++;
503  }
504  } else if (packet_code == PACKET_CODE_VIRGIN_RAW8_TOPBOT) {
506  sistrip::FEDBSChannelUnpacker::virginRawModeUnpacker(buffer->channel(iconn->fedCh()), 8);
507  while (unpacker.hasData()) {
508  samples.push_back((unpacker.adc() << 1));
509  unpacker++;
510  }
511  }
512  }
513  if (!samples.empty()) {
514  Registry regItem(key, 256 * ipair, virgin_work_digis_.size(), samples.size());
515  uint16_t physical;
516  uint16_t readout;
517  for (uint16_t i = 0, n = samples.size(); i < n; i++) {
518  physical = i % 128;
519  readoutOrder(physical, readout); // convert index from physical to readout order
520  (i / 128) ? readout = readout* 2 + 1 : readout = readout * 2; // un-multiplex data
521  virgin_work_digis_.push_back(SiStripRawDigi(samples[readout]));
522  }
523  virgin_work_registry_.push_back(regItem);
524  }
525  }
526 
527  else if ((!legacy_ && mode == sistrip::READOUT_MODE_PROC_RAW) ||
530  std::vector<uint16_t> samples;
531 
534  sistrip::FEDRawChannelUnpacker::procRawModeUnpacker(buffer->channel(iconn->fedCh()));
535 
537  while (unpacker.hasData()) {
538  samples.push_back(unpacker.adc());
539  unpacker++;
540  }
541 
542  if (!samples.empty()) {
543  Registry regItem(key, 256 * ipair, proc_work_digis_.size(), samples.size());
544  for (uint16_t i = 0, n = samples.size(); i < n; i++) {
545  proc_work_digis_.push_back(SiStripRawDigi(samples[i]));
546  }
547  proc_work_registry_.push_back(regItem);
548  }
549  }
550 
551  else if ((!legacy_ && mode == sistrip::READOUT_MODE_SCOPE) ||
553  std::vector<uint16_t> samples;
554 
557  sistrip::FEDRawChannelUnpacker::scopeModeUnpacker(buffer->channel(iconn->fedCh()));
558 
560  while (unpacker.hasData()) {
561  samples.push_back(unpacker.adc());
562  unpacker++;
563  }
564 
565  if (!samples.empty()) {
566  Registry regItem(key, 0, scope_work_digis_.size(), samples.size());
567  for (uint16_t i = 0, n = samples.size(); i < n; i++) {
568  scope_work_digis_.push_back(SiStripRawDigi(samples[i]));
569  }
570  scope_work_registry_.push_back(regItem);
571  }
572  }
573 
574  else { // Unknown readout mode! => assume scope mode
575 
576  warnings_.add((boost::format("Unknown FED readout mode (%1%)! Assuming SCOPE MODE...") % mode).str());
577 
578  std::vector<uint16_t> samples;
579 
582  sistrip::FEDRawChannelUnpacker::scopeModeUnpacker(buffer->channel(iconn->fedCh()));
583 
585  while (unpacker.hasData()) {
586  samples.push_back(unpacker.adc());
587  unpacker++;
588  }
589 
590  if (!samples.empty()) {
591  Registry regItem(key, 0, scope_work_digis_.size(), samples.size());
592  for (uint16_t i = 0, n = samples.size(); i < n; i++) {
593  scope_work_digis_.push_back(SiStripRawDigi(samples[i]));
594  }
595  scope_work_registry_.push_back(regItem);
596 
597  if (edm::isDebugEnabled()) {
598  std::stringstream ss;
599  ss << "Extracted " << samples.size() << " SCOPE MODE digis (samples[0] = " << samples[0]
600  << ") from FED id/ch " << iconn->fedId() << "/" << iconn->fedCh();
601  LogTrace("SiStripRawToDigi") << ss.str();
602  }
603  } else {
604  warnings_.add("No SM digis found!");
605  }
606  }
607  } // channel loop
608  } // fed loop
609 
610  // bad channels warning
611  unsigned int detIdsSize = detids.size();
612  if (edm::isDebugEnabled() && detIdsSize) {
613  std::ostringstream ss;
614  ss << "[sistrip::RawToDigiUnpacker::" << __func__ << "]"
615  << " Problems were found in data and " << detIdsSize << " channels could not be unpacked. "
616  << "See output of FED Hardware monitoring for more information. ";
618  }
619  if ((errorThreshold_ != 0) && (detIdsSize > errorThreshold_)) {
620  edm::LogError("TooManyErrors") << "Total number of errors = " << detIdsSize;
621  }
622 
623  // update DetSetVectors
624  update(scope_mode, virgin_raw, proc_raw, zero_suppr, cm_values);
625 
626  // increment event counter
627  event_++;
628 
629  // no longer first event!
630  if (first_) {
631  first_ = false;
632  }
633 
634  // final cleanup, just in case
636  }
637 
639  RawDigis& scope_mode, RawDigis& virgin_raw, RawDigis& proc_raw, Digis& zero_suppr, RawDigis& common_mode) {
640  if (!zs_work_registry_.empty()) {
641  std::sort(zs_work_registry_.begin(), zs_work_registry_.end());
642  std::vector<edm::DetSet<SiStripDigi> > sorted_and_merged;
643  sorted_and_merged.reserve(std::min(zs_work_registry_.size(), size_t(17000)));
644 
645  bool errorInData = false;
646  std::vector<Registry>::iterator it = zs_work_registry_.begin(), it2 = it + 1, end = zs_work_registry_.end();
647  while (it < end) {
648  sorted_and_merged.push_back(edm::DetSet<SiStripDigi>(it->detid));
649  std::vector<SiStripDigi>& digis = sorted_and_merged.back().data;
650  // first count how many digis we have
651  size_t len = it->length;
652  for (it2 = it + 1; (it2 != end) && (it2->detid == it->detid); ++it2) {
653  len += it2->length;
654  }
655  // reserve memory
656  digis.reserve(len);
657  // push them in
658  for (it2 = it + 0; (it2 != end) && (it2->detid == it->detid); ++it2) {
659  digis.insert(digis.end(), &zs_work_digis_[it2->index], &zs_work_digis_[it2->index + it2->length]);
660  }
661  it = it2;
662  }
663 
664  // check sorting
665  if (!__gnu_cxx::is_sorted(sorted_and_merged.begin(), sorted_and_merged.end())) {
666  // this is an error in the code: i DID sort it already!
667  throw cms::Exception("Bug Found")
668  << "Container must be already sorted!\nat " << __FILE__ << ", line " << __LINE__ << "\n";
669  }
670 
671  std::vector<edm::DetSet<SiStripDigi> >::iterator iii = sorted_and_merged.begin();
672  std::vector<edm::DetSet<SiStripDigi> >::iterator jjj = sorted_and_merged.end();
673  for (; iii != jjj; ++iii) {
674  if (!__gnu_cxx::is_sorted(iii->begin(), iii->end())) {
675  // this might be an error in the data, if the raws from one FED are not sorted
676  iii->clear();
677  errorInData = true;
678  }
679  }
680 
681  // output error
682  if (errorInData)
683  edm::LogWarning("CorruptData")
684  << "Some modules contained corrupted ZS raw data, and have been skipped in unpacking\n";
685 
686  // make output DetSetVector
687  edm::DetSetVector<SiStripDigi> zero_suppr_dsv(sorted_and_merged, true);
688  zero_suppr.swap(zero_suppr_dsv);
689  }
690 
691  // Populate final DetSetVector container with VR data
692  if (!virgin_work_registry_.empty()) {
693  std::sort(virgin_work_registry_.begin(), virgin_work_registry_.end());
694 
695  std::vector<edm::DetSet<SiStripRawDigi> > sorted_and_merged;
696  sorted_and_merged.reserve(std::min(virgin_work_registry_.size(), size_t(17000)));
697 
698  bool errorInData = false;
699  std::vector<Registry>::iterator it = virgin_work_registry_.begin(), it2, end = virgin_work_registry_.end();
700  while (it < end) {
701  sorted_and_merged.push_back(edm::DetSet<SiStripRawDigi>(it->detid));
702  std::vector<SiStripRawDigi>& digis = sorted_and_merged.back().data;
703 
704  bool isDetOk = true;
705  // first count how many digis we have
706  int maxFirstStrip = it->first;
707  for (it2 = it + 1; (it2 != end) && (it2->detid == it->detid); ++it2) {
708  // duplicated APV or data corruption. DO NOT 'break' here!
709  if (it2->first <= maxFirstStrip) {
710  isDetOk = false;
711  continue;
712  }
713  maxFirstStrip = it2->first;
714  }
715  if (!isDetOk) {
716  errorInData = true;
717  it = it2;
718  continue;
719  } // skip whole det
720 
721  // make room for 256 * (max_apv_pair + 1) Raw Digis
722  digis.resize(maxFirstStrip + 256);
723  // push them in
724  for (it2 = it + 0; (it2 != end) && (it2->detid == it->detid); ++it2) {
725  // data corruption. DO NOT 'break' here
726  if (it->length != 256) {
727  isDetOk = false;
728  continue;
729  }
730  std::copy(&virgin_work_digis_[it2->index], &virgin_work_digis_[it2->index + it2->length], &digis[it2->first]);
731  }
732  if (!isDetOk) {
733  errorInData = true;
734  digis.clear();
735  it = it2;
736  continue;
737  } // skip whole det
738  it = it2;
739  }
740 
741  // output error
742  if (errorInData)
743  edm::LogWarning("CorruptData")
744  << "Some modules contained corrupted virgin raw data, and have been skipped in unpacking\n";
745 
746  // check sorting
747  if (!__gnu_cxx::is_sorted(sorted_and_merged.begin(), sorted_and_merged.end())) {
748  // this is an error in the code: i DID sort it already!
749  throw cms::Exception("Bug Found")
750  << "Container must be already sorted!\nat " << __FILE__ << ", line " << __LINE__ << "\n";
751  }
752 
753  // make output DetSetVector
754  edm::DetSetVector<SiStripRawDigi> virgin_raw_dsv(sorted_and_merged, true);
755  virgin_raw.swap(virgin_raw_dsv);
756  }
757 
758  // Populate final DetSetVector container with VR data
759  if (!proc_work_registry_.empty()) {
760  std::sort(proc_work_registry_.begin(), proc_work_registry_.end());
761 
762  std::vector<edm::DetSet<SiStripRawDigi> > sorted_and_merged;
763  sorted_and_merged.reserve(std::min(proc_work_registry_.size(), size_t(17000)));
764 
765  bool errorInData = false;
766  std::vector<Registry>::iterator it = proc_work_registry_.begin(), it2, end = proc_work_registry_.end();
767  while (it < end) {
768  sorted_and_merged.push_back(edm::DetSet<SiStripRawDigi>(it->detid));
769  std::vector<SiStripRawDigi>& digis = sorted_and_merged.back().data;
770 
771  bool isDetOk = true;
772  // first count how many digis we have
773  int maxFirstStrip = it->first;
774  for (it2 = it + 1; (it2 != end) && (it2->detid == it->detid); ++it2) {
775  // duplicated APV or data corruption. DO NOT 'break' here!
776  if (it2->first <= maxFirstStrip) {
777  isDetOk = false;
778  continue;
779  }
780  maxFirstStrip = it2->first;
781  }
782  // skip whole det
783  if (!isDetOk) {
784  errorInData = true;
785  it = it2;
786  continue;
787  }
788 
789  // make room for 256 * (max_apv_pair + 1) Raw Digis
790  digis.resize(maxFirstStrip + 256);
791  // push them in
792  for (it2 = it + 0; (it2 != end) && (it2->detid == it->detid); ++it2) {
793  // data corruption. DO NOT 'break' here
794  if (it->length != 256) {
795  isDetOk = false;
796  continue;
797  }
798  std::copy(&proc_work_digis_[it2->index], &proc_work_digis_[it2->index + it2->length], &digis[it2->first]);
799  }
800  // skip whole det
801  if (!isDetOk) {
802  errorInData = true;
803  digis.clear();
804  it = it2;
805  continue;
806  }
807  it = it2;
808  }
809 
810  // output error
811  if (errorInData)
812  edm::LogWarning("CorruptData")
813  << "Some modules contained corrupted proc raw data, and have been skipped in unpacking\n";
814 
815  // check sorting
816  if (!__gnu_cxx::is_sorted(sorted_and_merged.begin(), sorted_and_merged.end())) {
817  // this is an error in the code: i DID sort it already!
818  throw cms::Exception("Bug Found")
819  << "Container must be already sorted!\nat " << __FILE__ << ", line " << __LINE__ << "\n";
820  }
821 
822  // make output DetSetVector
823  edm::DetSetVector<SiStripRawDigi> proc_raw_dsv(sorted_and_merged, true);
824  proc_raw.swap(proc_raw_dsv);
825  }
826 
827  // Populate final DetSetVector container with SM data
828  if (!scope_work_registry_.empty()) {
829  std::sort(scope_work_registry_.begin(), scope_work_registry_.end());
830 
831  std::vector<edm::DetSet<SiStripRawDigi> > sorted_and_merged;
832  sorted_and_merged.reserve(scope_work_registry_.size());
833 
834  bool errorInData = false;
835  std::vector<Registry>::iterator it, end;
836  for (it = scope_work_registry_.begin(), end = scope_work_registry_.end(); it != end; ++it) {
837  sorted_and_merged.push_back(edm::DetSet<SiStripRawDigi>(it->detid));
838  std::vector<SiStripRawDigi>& digis = sorted_and_merged.back().data;
839  digis.insert(digis.end(), &scope_work_digis_[it->index], &scope_work_digis_[it->index + it->length]);
840 
841  if ((it + 1 != end) && (it->detid == (it + 1)->detid)) {
842  errorInData = true;
843  // let's skip *all* the detsets for that key, as we don't know which is the correct one!
844  do {
845  ++it;
846  } while ((it + 1 != end) && (it->detid == (it + 1)->detid));
847  }
848  }
849 
850  // output error
851  if (errorInData)
852  edm::LogWarning("CorruptData")
853  << "Some fed keys contained corrupted scope mode data, and have been skipped in unpacking\n";
854 
855  // check sorting
856  if (!__gnu_cxx::is_sorted(sorted_and_merged.begin(), sorted_and_merged.end())) {
857  // this is an error in the code: i DID sort it already!
858  throw cms::Exception("Bug Found")
859  << "Container must be already sorted!\nat " << __FILE__ << ", line " << __LINE__ << "\n";
860  }
861 
862  // make output DetSetVector
863  edm::DetSetVector<SiStripRawDigi> scope_mode_dsv(sorted_and_merged, true);
864  scope_mode.swap(scope_mode_dsv);
865  }
866 
867  // Populate DetSetVector with Common Mode values
868  if (extractCm_) {
869  // Populate final DetSetVector container with VR data
870  if (!cm_work_registry_.empty()) {
871  std::sort(cm_work_registry_.begin(), cm_work_registry_.end());
872 
873  std::vector<edm::DetSet<SiStripRawDigi> > sorted_and_merged;
874  sorted_and_merged.reserve(std::min(cm_work_registry_.size(), size_t(17000)));
875 
876  bool errorInData = false;
877  std::vector<Registry>::iterator it = cm_work_registry_.begin(), it2, end = cm_work_registry_.end();
878  while (it < end) {
879  sorted_and_merged.push_back(edm::DetSet<SiStripRawDigi>(it->detid));
880  std::vector<SiStripRawDigi>& digis = sorted_and_merged.back().data;
881 
882  bool isDetOk = true;
883  // first count how many digis we have
884  int maxFirstStrip = it->first;
885  for (it2 = it + 1; (it2 != end) && (it2->detid == it->detid); ++it2) {
886  // duplicated APV or data corruption. DO NOT 'break' here!
887  if (it2->first <= maxFirstStrip) {
888  isDetOk = false;
889  continue;
890  }
891  maxFirstStrip = it2->first;
892  }
893  if (!isDetOk) {
894  errorInData = true;
895  it = it2;
896  continue;
897  } // skip whole det
898 
899  // make room for 2 * (max_apv_pair + 1) Common mode values
900  digis.resize(maxFirstStrip + 2);
901  // push them in
902  for (it2 = it + 0; (it2 != end) && (it2->detid == it->detid); ++it2) {
903  // data corruption. DO NOT 'break' here
904  if (it->length != 2) {
905  isDetOk = false;
906  continue;
907  }
908  std::copy(&cm_work_digis_[it2->index], &cm_work_digis_[it2->index + it2->length], &digis[it2->first]);
909  }
910  if (!isDetOk) {
911  errorInData = true;
912  digis.clear();
913  it = it2;
914  continue;
915  } // skip whole det
916  it = it2;
917  }
918 
919  // output error
920  if (errorInData)
921  edm::LogWarning("CorruptData")
922  << "Some modules contained corrupted common mode data, and have been skipped in unpacking\n";
923 
924  // check sorting
925  if (!__gnu_cxx::is_sorted(sorted_and_merged.begin(), sorted_and_merged.end())) {
926  // this is an error in the code: i DID sort it already!
927  throw cms::Exception("Bug Found")
928  << "Container must be already sorted!\nat " << __FILE__ << ", line " << __LINE__ << "\n";
929  }
930 
931  // make output DetSetVector
932  edm::DetSetVector<SiStripRawDigi> common_mode_dsv(sorted_and_merged, true);
933  common_mode.swap(common_mode_dsv);
934  }
935  }
936  }
937 
939  // Clear working areas and registries
940 
941  localRA.update(zs_work_digis_.size());
942  zs_work_registry_.clear();
943  zs_work_digis_.clear();
944  zs_work_digis_.shrink_to_fit();
945  assert(zs_work_digis_.capacity() == 0);
946  virgin_work_registry_.clear();
947  virgin_work_digis_.clear();
948  proc_work_registry_.clear();
949  proc_work_digis_.clear();
950  scope_work_registry_.clear();
951  scope_work_digis_.clear();
952  cm_work_registry_.clear();
953  cm_work_digis_.clear();
954  }
955 
958  const uint32_t& event) {
959  // Pointer to data (recast as 32-bit words) and number of 32-bit words
960  uint32_t* data_u32 = nullptr;
961  uint32_t size_u32 = 0;
962 
963  // Search mode
964  if (triggerFedId_ < 0) {
965  uint16_t ifed = 0;
966  while (triggerFedId_ < 0 && ifed < 1 + FEDNumbering::lastFEDId()) {
967  const FEDRawData& trigger_fed = buffers.FEDData(ifed);
968  if (trigger_fed.data() && trigger_fed.size()) {
969  uint8_t* temp = const_cast<uint8_t*>(trigger_fed.data());
970  data_u32 = reinterpret_cast<uint32_t*>(temp) + FEDHeader::length / sizeof(uint32_t) + 1;
971  size_u32 = trigger_fed.size() / sizeof(uint32_t) - FEDHeader::length / sizeof(uint32_t) - 1;
972  const FEDTrailer fedTrailer(temp + trigger_fed.size() - FEDTrailer::length);
973  if (fedTrailer.conscheck() == 0xDEADFACE) {
974  triggerFedId_ = ifed;
975  if (edm::isDebugEnabled()) {
976  std::stringstream ss;
977  ss << "[sistrip::RawToDigiUnpacker::" << __func__ << "]"
978  << " Search mode for 'trigger FED' activated!"
979  << " Found 'trigger FED' info with id " << triggerFedId_;
980  LogTrace("SiStripRawToDigi") << ss.str();
981  }
982  }
983  }
984  ifed++;
985  }
986  if (triggerFedId_ < 0) {
987  triggerFedId_ = 0;
988  if (edm::isDebugEnabled()) {
989  std::stringstream ss;
990  ss << "[sistrip::RawToDigiUnpacker::" << __func__ << "]"
991  << " Search mode for 'trigger FED' activated!"
992  << " 'Trigger FED' info not found!";
994  }
995  }
996  }
997 
998  // "Trigger FED" id given in .cfg file
999  else if (triggerFedId_ > 0) {
1000  const FEDRawData& trigger_fed = buffers.FEDData(triggerFedId_);
1001  if (trigger_fed.data() && trigger_fed.size()) {
1002  uint8_t* temp = const_cast<uint8_t*>(trigger_fed.data());
1003  data_u32 = reinterpret_cast<uint32_t*>(temp) + FEDHeader::length / sizeof(uint32_t) + 1;
1004  size_u32 = trigger_fed.size() / sizeof(uint32_t) - FEDHeader::length / sizeof(uint32_t) - 1;
1005  const FEDTrailer fedTrailer(temp + trigger_fed.size() - FEDTrailer::length);
1006  if (fedTrailer.conscheck() != 0xDEADFACE) {
1007  if (edm::isDebugEnabled()) {
1008  edm::LogWarning(sistrip::mlRawToDigi_) << "[sistrip::RawToDigiUnpacker::" << __func__ << "]"
1009  << " Unexpected stamp found in DAQ trailer (ie, not 0xDEADFACE)!"
1010  << " Buffer appears not to contain 'trigger FED' data!";
1011  }
1012  triggerFedId_ = 0;
1013  }
1014  }
1015 
1016  } else {
1017  triggerFedId_ = 0;
1018  data_u32 = nullptr;
1019  size_u32 = 0;
1020  }
1021 
1022  // Populate summary object with commissioning information
1023  if (triggerFedId_ > 0) {
1024  // Some checks
1025  if (!data_u32) {
1026  if (edm::isDebugEnabled()) {
1027  std::stringstream ss;
1028  ss << "[sistrip::RawToDigiUnpacker::" << __func__ << "]"
1029  << " NULL pointer to 'trigger FED' data";
1031  }
1032  return;
1033  }
1034  if (size_u32 < sizeof(TFHeaderDescription) / sizeof(uint32_t)) {
1035  if (edm::isDebugEnabled()) {
1036  std::stringstream ss;
1037  ss << "[sistrip::RawToDigiUnpacker::" << __func__ << "]"
1038  << " Unexpected 'Trigger FED' data size [32-bit words]: " << size_u32;
1040  }
1041  return;
1042  }
1043 
1044  // Write event-specific data to event
1046  summary.event(static_cast<uint32_t>(header->getFedEventNumber()));
1047  summary.bx(static_cast<uint32_t>(header->getBunchCrossing()));
1048 
1049  // Write commissioning information to event
1050  uint32_t hsize = sizeof(TFHeaderDescription) / sizeof(uint32_t);
1051  uint32_t* head = &data_u32[hsize];
1052  summary.commissioningInfo(head, event);
1053  summary.triggerFed(triggerFedId_);
1054  }
1055 
1056  // Some debug
1057  if (summary.isSet() && once_) {
1058  if (edm::isDebugEnabled()) {
1059  std::stringstream ss;
1060  ss << "[sistrip::RawToDigiUnpacker::" << __func__ << "]"
1061  << " EventSummary built from \"trigger FED\":" << std::endl
1062  << summary;
1063  LogTrace("SiStripRawToDigi") << ss.str();
1064  }
1065  once_ = false;
1066  }
1067  }
1068 
1070  // Check size of input buffer
1071  if (input.size() < 24) {
1072  output.resize(input.size()); // Return UNadjusted buffer start position and size
1073  memcpy(output.data(), input.data(), input.size());
1074  if (edm::isDebugEnabled()) {
1075  std::stringstream ss;
1076  ss << "[sistrip::RawToDigiUnpacker::" << __func__ << "] "
1077  << "Input FEDRawData with FED id " << fed_id << " has size " << input.size();
1079  }
1080  return;
1081  }
1082 
1083  // Iterator through buffer to find DAQ header
1084  bool found = false;
1085  uint16_t ichar = 0;
1086  while (ichar < input.size() - 16 && !found) {
1087  uint16_t offset =
1088  headerBytes_ < 0 ? ichar : headerBytes_; // Negative value means use "search mode" to find DAQ header
1089  uint32_t* input_u32 = reinterpret_cast<uint32_t*>(const_cast<unsigned char*>(input.data()) + offset);
1090  uint32_t* fed_trailer = reinterpret_cast<uint32_t*>(const_cast<unsigned char*>(input.data()) + input.size() - 8);
1091 
1092  // see info on FED 32-bit swapping at end-of-file
1093 
1094  bool old_vme_header = (input_u32[0] & 0xF0000000) == 0x50000000 && (fed_trailer[0] & 0xF0000000) == 0xA0000000 &&
1095  ((fed_trailer[0] & 0x00FFFFFF) * 0x8) == (input.size() - offset);
1096 
1097  bool old_slink_header = (input_u32[1] & 0xF0000000) == 0x50000000 &&
1098  (fed_trailer[1] & 0xF0000000) == 0xA0000000 &&
1099  ((fed_trailer[1] & 0x00FFFFFF) * 0x8) == (input.size() - offset);
1100 
1101  bool old_slink_payload = (input_u32[3] & 0xFF000000) == 0xED000000;
1102 
1103  bool new_buffer_format = (input_u32[2] & 0xFF000000) == 0xC5000000;
1104 
1105  if (old_vme_header) {
1106  // Found DAQ header at byte position 'offset'
1107  found = true;
1108  output.resize(input.size() - offset);
1109  memcpy(output.data(), // target
1110  input.data() + offset, // source
1111  input.size() - offset); // nbytes
1112  if (headerBytes_ < 0) {
1113  if (edm::isDebugEnabled()) {
1114  std::stringstream ss;
1115  ss << "[sistrip::RawToDigiUnpacker::" << __func__ << "]"
1116  << " Buffer for FED id " << fed_id << " has been found at byte position " << offset << " with a size of "
1117  << input.size() - offset << " bytes."
1118  << " Adjust the configurable 'AppendedBytes' to " << offset;
1119  LogTrace("SiStripRawToDigi") << ss.str();
1120  }
1121  }
1122 
1123  } else if (old_slink_header) {
1124  if (old_slink_payload) {
1125  // Found DAQ header (with MSB and LSB 32-bit words swapped) at byte position 'offset'
1126  found = true;
1127  output.resize(input.size() - offset);
1128  uint32_t* output_u32 = reinterpret_cast<uint32_t*>(const_cast<unsigned char*>(output.data()));
1129  uint16_t iter = offset;
1130  while (iter < output.size() / sizeof(uint32_t)) {
1131  output_u32[iter] = input_u32[iter + 1];
1132  output_u32[iter + 1] = input_u32[iter];
1133  iter += 2;
1134  }
1135  if (headerBytes_ < 0) {
1136  if (edm::isDebugEnabled()) {
1137  std::stringstream ss;
1138  ss << "[sistrip::RawToDigiUnpacker::" << __func__ << "]"
1139  << " Buffer (with MSB and LSB 32-bit words swapped) for FED id " << fed_id
1140  << " has been found at byte position " << offset << " with a size of " << output.size() << " bytes."
1141  << " Adjust the configurable 'AppendedBytes' to " << offset;
1142  LogTrace("SiStripRawToDigi") << ss.str();
1143  }
1144  }
1145 
1146  } else if (new_buffer_format) {
1147  // Found DAQ header at byte position 'offset'
1148  found = true;
1149  output.resize(input.size() - offset);
1150  memcpy(output.data(), // target
1151  input.data() + offset, // source
1152  input.size() - offset); // nbytes
1153  if (headerBytes_ < 0) {
1154  if (edm::isDebugEnabled()) {
1155  std::stringstream ss;
1156  ss << "[sistrip::RawToDigiUnpacker::" << __func__ << "]"
1157  << " Buffer for FED id " << fed_id << " has been found at byte position " << offset
1158  << " with a size of " << input.size() - offset << " bytes."
1159  << " Adjust the configurable 'AppendedBytes' to " << offset;
1160  LogTrace("SiStripRawToDigi") << ss.str();
1161  }
1162  }
1163 
1164  } else {
1165  headerBytes_ < 0 ? found = false : found = true;
1166  }
1167  } else {
1168  headerBytes_ < 0 ? found = false : found = true;
1169  }
1170  ichar++;
1171  }
1172 
1173  // Check size of output buffer
1174  if (output.size() == 0) {
1175  // Did not find DAQ header after search => return buffer with null size
1176  output.resize(0); //@@ NULL SIZE
1177  memcpy(output.data(), input.data(), 0); //@@ NULL SIZE
1178  if (edm::isDebugEnabled()) {
1179  std::stringstream ss;
1180  if (headerBytes_ < 0) {
1181  ss << "[sistrip::RawToDigiUnpacker::" << __func__ << "]"
1182  << " DAQ header not found within buffer for FED id: " << fed_id;
1183  } else {
1184  uint32_t* input_u32 = reinterpret_cast<uint32_t*>(const_cast<unsigned char*>(input.data()));
1185  ss << "[sistrip::RawToDigiUnpacker::" << __func__ << "]"
1186  << " DAQ header not found at expected location for FED id: " << fed_id << std::endl
1187  << " First 64-bit word of buffer is 0x" << std::hex << std::setfill('0') << std::setw(8) << input_u32[0]
1188  << std::setfill('0') << std::setw(8) << input_u32[1] << std::dec << std::endl
1189  << " Adjust 'AppendedBytes' configurable to '-1' to activate 'search mode'";
1190  }
1192  }
1193 
1194  } else if (output.size() < 24) { // Found DAQ header after search, but too few words
1195 
1196  if (edm::isDebugEnabled()) {
1197  std::stringstream ss;
1198  ss << "[sistrip::RawToDigiUnpacker::" << __func__ << "]"
1199  << " Unexpected buffer size! FEDRawData with FED id " << fed_id << " has size " << output.size();
1201  }
1202  }
1203  }
1204 
1206  summary.event(fed.daqHeader().l1ID());
1207  summary.bx(fed.daqHeader().bxID());
1208 
1209  // Retrieve contents of DAQ registers
1210 
1211  sistrip::FEDDAQEventType readout_mode = fed.daqEventType();
1212  uint32_t daq1 = sistrip::invalid32_;
1213  uint32_t daq2 = sistrip::invalid32_;
1214 
1216  const sistrip::FEDFullDebugHeader* header = nullptr;
1217  header = dynamic_cast<const sistrip::FEDFullDebugHeader*>(fed.feHeader());
1218  daq1 = static_cast<uint32_t>(header->daqRegister());
1219  daq2 = static_cast<uint32_t>(header->daqRegister2());
1220  }
1221 
1222  // If FED DAQ registers contain info, update (and possibly overwrite) EventSummary
1223  if (daq1 != 0 && daq1 != sistrip::invalid32_) {
1224  summary.triggerFed(triggerFedId_);
1225  summary.fedReadoutMode(readout_mode);
1226  summary.commissioningInfo(daq1, daq2);
1227 
1228  if (summary.isSet() && once_) {
1229  if (edm::isDebugEnabled()) {
1230  std::stringstream ss;
1231  ss << "[sistrip::RawToDigiUnpacker::" << __func__ << "]"
1232  << " EventSummary built from FED DAQ registers:" << std::endl
1233  << summary;
1234  LogTrace("SiStripRawToDigi") << ss.str();
1235  }
1236  once_ = false;
1237  }
1238  }
1239  }
1240 
1241  void RawToDigiUnpacker::dumpRawData(uint16_t fed_id, const FEDRawData& buffer, std::stringstream& ss) {
1242  ss << "[sistrip::RawToDigiUnpacker::" << __func__ << "]"
1243  << " Dump of buffer for FED id " << fed_id << std::endl
1244  << " Buffer contains " << buffer.size() << " bytes (NB: payload is byte-swapped)" << std::endl;
1245 
1246  if (false) {
1247  uint32_t* buffer_u32 = reinterpret_cast<uint32_t*>(const_cast<unsigned char*>(buffer.data()));
1248  unsigned int empty = 0;
1249 
1250  ss << "Byte-> 4 5 6 7 0 1 2 3\n";
1251  for (uint32_t i = 0; i < buffer.size() / 8; i++) {
1252  unsigned int temp0 = buffer_u32[i * 2] & sistrip::invalid32_;
1253  unsigned int temp1 = buffer_u32[i * 2 + 1] & sistrip::invalid32_;
1254  if (!temp0 && !temp1) {
1255  empty++;
1256  } else {
1257  if (empty) {
1258  ss << " [ empty words ]" << std::endl;
1259  empty = 0;
1260  }
1261  ss << std::dec << std::setfill(' ') << std::setw(6) << i * 8 << ": " << std::hex << std::setfill('0')
1262  << std::setw(8) << temp0 << std::setfill('0') << std::setw(8) << temp1 << std::dec << std::endl;
1263  }
1264  }
1265 
1266  } else {
1267  ss << " Byte | <---- Byte order ----< | Byte" << std::endl;
1268  ss << " cntr | 7 6 5 4 3 2 1 0 | cntr" << std::endl;
1269  for (uint32_t i = 0; i < buffer.size() / 8; i++) {
1270  //if ( i>=20 && ((i+4)<(buffer.size()/8)) ) { continue; }
1271  uint16_t tmp0 = buffer.data()[i * 8 + 0] & 0xFF;
1272  uint16_t tmp1 = buffer.data()[i * 8 + 1] & 0xFF;
1273  uint16_t tmp2 = buffer.data()[i * 8 + 2] & 0xFF;
1274  uint16_t tmp3 = buffer.data()[i * 8 + 3] & 0xFF;
1275  uint16_t tmp4 = buffer.data()[i * 8 + 4] & 0xFF;
1276  uint16_t tmp5 = buffer.data()[i * 8 + 5] & 0xFF;
1277  uint16_t tmp6 = buffer.data()[i * 8 + 6] & 0xFF;
1278  uint16_t tmp7 = buffer.data()[i * 8 + 7] & 0xFF;
1279  // if ( !tmp0 && !tmp1 && !tmp2 && !tmp3 &&
1280  // !tmp4 && !tmp5 && !tmp6 && !tmp7 ) { empty++; }
1281  // else {
1282  // if ( empty ) {
1283  // ss << " [.."
1284  // << std::dec << std::setfill('.') << std::setw(4) << empty
1285  // << " null words....]" << std::endl;
1286  // empty = 0;
1287  // }
1288  ss << std::dec << std::setfill(' ') << std::setw(6) << i * 8 + 7 << " : " << std::hex << std::setfill('0')
1289  << std::setw(2) << tmp7 << " " << std::setfill('0') << std::setw(2) << tmp6 << " " << std::setfill('0')
1290  << std::setw(2) << tmp5 << " " << std::setfill('0') << std::setw(2) << tmp4 << " " << std::setfill('0')
1291  << std::setw(2) << tmp3 << " " << std::setfill('0') << std::setw(2) << tmp2 << " " << std::setfill('0')
1292  << std::setw(2) << tmp1 << " " << std::setfill('0') << std::setw(2) << tmp0 << std::dec << " :"
1293  << std::setfill(' ') << std::setw(6) << i * 8 << std::endl;
1294  // }
1295  }
1296  }
1297  ss << "[sistrip::RawToDigiUnpacker::" << __func__ << "]"
1298  << " End of FED buffer";
1299  }
1300 
1302  method_name = "sistrip::RawToDigiUnpacker::" + method_name;
1303  try {
1304  throw; // rethrow caught exception to be dealt with below
1305  } catch (const cms::Exception& e) {
1306  //throw e; // rethrow cms::Exception to be caught by framework
1307  } catch (const std::exception& e) {
1308  if (edm::isDebugEnabled()) {
1309  std::stringstream ss;
1310  ss << "[sistrip::RawToDigiUnpacker::" << __func__ << "]"
1311  << " Caught std::exception!" << std::endl;
1312  if (!extra_info.empty()) {
1313  ss << " Information: " << extra_info << std::endl;
1314  }
1315  ss << " Caught std::exception in [" << method_name << "] with message:" << std::endl << e.what();
1317  }
1318  //throw cms::Exception(sistrip::mlRawToDigi_) << ss.str();
1319  } catch (...) {
1320  if (edm::isDebugEnabled()) {
1321  std::stringstream ss;
1322  ss << "[sistrip::RawToDigiUnpacker::" << __func__ << "]"
1323  << " Caught unknown exception!" << std::endl;
1324  if (!extra_info.empty()) {
1325  ss << " Information: " << extra_info << std::endl;
1326  }
1327  ss << "Caught unknown exception in [" << method_name << "]" << std::endl;
1329  }
1330  //throw cms::Exception(sistrip::mlRawToDigi_) << ss.str();
1331  }
1332  }
1333 
1334 } // namespace sistrip
1335 
1336 /*
1337 
1338 Some info on FED buffer 32-bit word swapping.
1339 
1340 Table below indicates if data are swapped relative to the "old"
1341 VME format (as originally expected by the Fed9UEvent class).
1342 
1343 -------------------------------------------
1344 | SWAPPED? | DATA FORMAT |
1345 | (wrt "OLD") | OLD (0xED) | NEW (0xC5) |
1346 | | VME | SLINK | VME | SLINK |
1347 -------------------------------------------
1348 | DAQ HEADER | N | Y | Y | Y |
1349 | TRK HEADER | N | Y | N | N |
1350 | PAYLOAD | N | Y | N | N |
1351 | DAQ TRAILER | N | Y | Y | Y |
1352 -------------------------------------------
1353 
1354 So, in code, we check in code order of bytes in DAQ header/trailer only:
1355 -> if "old_vme_header", then old format read out via vme, so do nothing.
1356 -> else if "old_slink_header", then data may be wrapped, so check additionally the TRK header:
1357 ---> if "old_slink_payload", then old format read out via slink, so swap all data;
1358 ---> else if "new_buffer_format", then new format, handled internally by Fed9UEvent, so do nothing.
1359 
1360 Pattern matching to find DAQ and tracker headers, and DAQ trailer:
1361 DAQ header, 4 bits, in field |BOE_1| with value 0x5
1362 DAQ trailer, 4 bits, in field |EOE_1| with value 0xA
1363 TRK header, 8 bits, in field |Hdr format| with value 0xED or 0xC5
1364 
1365 -------------------------------------------------------------------------------------------
1366 | SWAPPED? | DATA FORMAT |
1367 | (wrt "OLD") | OLD (0xED) | NEW (0xC5) |
1368 | | VME | SLINK | VME | SLINK |
1369 -------------------------------------------------------------------------------------------
1370 | DAQ HEADER | ........5....... | 5............... | 5............... | 5............... |
1371 | TRK HEADER | ........ED...... | ED.............. | ........C5...... | ........C5...... |
1372 | PAYLOAD | ..........EA.... | ..EA............ | ..EA............ | ............EA.. |
1373 | DAQ TRAILER | ........A....... | A............... | A............... | A............... |
1374 -------------------------------------------------------------------------------------------
1375 
1376 */
void triggerFed(const FEDRawDataCollection &, SiStripEventSummary &, const uint32_t &event)
trigger info
static FEDRawChannelUnpacker procRawModeUnpacker(const FEDChannel &channel)
size_type size() const
Definition: EDCollection.h:82
static const uint8_t PACKET_CODE_ZERO_SUPPRESSED8_BOTBOT
bool isDebugEnabled()
void update(RawDigis &scope_mode, RawDigis &virgin_raw, RawDigis &proc_raw, Digis &zero_suppr, RawDigis &common_mode)
fill DetSetVectors using registries
std::vector< Registry > proc_work_registry_
void updateEventSummary(const sistrip::FEDBuffer &, SiStripEventSummary &)
sets the SiStripEventSummary -> not yet implemented for FEDBuffer class
static FEDZSChannelUnpacker zeroSuppressedModeUnpacker(const FEDChannel &channel)
std::vector< SiStripDigi > zs_work_digis_
digi collections
std::vector< Registry > scope_work_registry_
void cleanupWorkVectors()
method to clear registries and digi collections
static const uint32_t length
Definition: FEDTrailer.h:57
std::vector< Registry > zs_work_registry_
registries
static FEDZSChannelUnpacker preMixRawModeUnpacker(const FEDChannel &channel)
static const uint32_t invalid32_
Definition: Constants.h:15
void locateStartOfFedBuffer(const uint16_t &fed_id, const FEDRawData &input, FEDRawData &output)
Removes any data appended prior to FED buffer and reorders 32-bit words if swapped.
static const uint32_t length
Definition: FEDHeader.h:54
static FEDRawChannelUnpacker scopeModeUnpacker(const FEDChannel &channel)
static FEDRawChannelUnpacker virginRawModeUnpacker(const FEDChannel &channel)
static FEDBSChannelUnpacker zeroSuppressedModeUnpacker(const FEDChannel &channel, uint16_t num_bits)
static const char mlRawToDigi_[]
void push_back(T const &t)
Definition: EDCollection.h:60
char const * what() const override
Definition: Exception.cc:103
unsigned long getBunchCrossing()
static FEDBSChannelUnpacker zeroSuppressedLiteModeUnpacker(const FEDChannel &channel, uint16_t num_bits)
static FEDBSChannelUnpacker virginRawModeUnpacker(const FEDChannel &channel, uint16_t num_bits)
const FEDFEHeader * feHeader() const
void swap(DetSetVector &other)
size_t size() const
Lenght of the data buffer in bytes.
Definition: FEDRawData.h:45
sistrip classes
FEDDAQEventType daqEventType() const
private class to register start and end index of digis in a collection
static std::string const input
Definition: EdmProvDump.cc:48
static const uint8_t PACKET_CODE_ZERO_SUPPRESSED8_TOPBOT
static const uint8_t PACKET_CODE_ZERO_SUPPRESSED10
const sistrip::RunType & runType() const
unsigned long getFedEventNumber()
std::vector< SiStripRawDigi > virgin_work_digis_
static const uint8_t PACKET_CODE_VIRGIN_RAW10
const uint32_t & bx() const
void readoutOrder(uint16_t &physical_order, uint16_t &readout_order)
order of strips
~RawToDigiUnpacker()
default constructor
static const uint8_t PACKET_CODE_ZERO_SUPPRESSED
const FEDRawData & FEDData(int fedid) const
retrieve data for fed
static void dumpRawData(uint16_t fed_id, const FEDRawData &, std::stringstream &)
dumps raw data to stdout (NB: payload is byte-swapped,headers/trailer are not).
void resize(size_t newsize)
Definition: FEDRawData.cc:28
void commissioningInfo(const uint32_t *const buffer, const uint32_t &event)
const uint32_t & event() const
FedsConstIterRange fedIds() const
FEDHeaderType headerType() const
std::vector< SiStripRawDigi > scope_work_digis_
#define end
Definition: vmac.h:39
T min(T a, T b)
Definition: MathUtil.h:58
A Digi for the silicon strip detector, containing both strip and adc information, and suitable for st...
Definition: SiStripDigi.h:12
static const uint8_t PACKET_CODE_VIRGIN_RAW8_TOPBOT
std::vector< SiStripRawDigi > proc_work_digis_
#define LogTrace(id)
void handleException(std::string method_name, std::string extra_info="")
catches all possible exceptions and rethrows them as cms::Exceptions
void add(const std::string &message, const std::string &details="")
void reserve(size_type n)
Definition: EDCollection.h:92
std::vector< SiStripRawDigi > cm_work_digis_
static const uint8_t PACKET_CODE_VIRGIN_RAW8_BOTBOT
static FEDZSChannelUnpacker zeroSuppressedLiteModeUnpacker(const FEDChannel &channel)
static const uint16_t FEDCH_PER_FEUNIT
uint16_t triggerFed() const
static const uint16_t invalid_
Definition: Constants.h:16
ConnsConstIterRange fedConnections(uint16_t fed_id) const
chan
lumi = TPaveText(lowX+0.38, lowY+0.061, lowX+0.45, lowY+0.161, "NDC") lumi.SetBorderSize( 0 ) lumi...
Contains cabling info at the device level, including DetId, APV pair numbers, hardware addresses...
const sistrip::FedReadoutMode & fedReadoutMode() const
HLT enums.
void event_()
const unsigned char * data() const
Return a const pointer to the beginning of the data buffer.
Definition: FEDRawData.cc:24
void createDigis(const SiStripFedCabling &, const FEDRawDataCollection &, SiStripEventSummary &, RawDigis &scope_mode, RawDigis &virgin_raw, RawDigis &proc_raw, Digis &zero_suppr, DetIdCollection &, RawDigis &common_mode)
creates digis
std::vector< Registry > cm_work_registry_
A Digi for the silicon strip detector, containing only adc information, and suitable for storing raw ...
#define str(s)
static constexpr int lastFEDId()
Definition: FEDNumbering.h:19
static const uint8_t PACKET_CODE_VIRGIN_RAW
std::vector< Registry > virgin_work_registry_
Definition: event.py:1
RawToDigiUnpacker()=delete
private default constructor