File indexing completed on 2024-09-07 04:36:16
0001 #include <iostream>
0002 #include <sstream>
0003 #include <iomanip>
0004 #include <ext/algorithm>
0005
0006 #include <fmt/format.h>
0007
0008 #include "CondFormats/SiStripObjects/interface/SiStripFedCabling.h"
0009 #include "DataFormats/Common/interface/DetSet.h"
0010 #include "DataFormats/FEDRawData/interface/FEDHeader.h"
0011 #include "DataFormats/FEDRawData/interface/FEDNumbering.h"
0012 #include "DataFormats/FEDRawData/interface/FEDRawDataCollection.h"
0013 #include "DataFormats/FEDRawData/interface/FEDTrailer.h"
0014 #include "DataFormats/SiStripCommon/interface/SiStripConstants.h"
0015 #include "DataFormats/SiStripCommon/interface/SiStripEventSummary.h"
0016 #include "DataFormats/SiStripDigi/interface/SiStripDigi.h"
0017 #include "DataFormats/SiStripDigi/interface/SiStripRawDigi.h"
0018 #include "EventFilter/SiStripRawToDigi/interface/TFHeaderDescription.h"
0019 #include "FWCore/MessageLogger/interface/MessageLogger.h"
0020 #include "FWCore/Utilities/interface/Exception.h"
0021 #include "FWCore/Utilities/interface/RunningAverage.h"
0022
0023 #include "SiStripRawToDigiUnpacker.h"
0024
0025 namespace sistrip {
0026
0027 RawToDigiUnpacker::RawToDigiUnpacker(int16_t appended_bytes,
0028 int16_t fed_buffer_dump_freq,
0029 int16_t fed_event_dump_freq,
0030 int16_t trigger_fed_id,
0031 bool using_fed_key,
0032 bool unpack_bad_channels,
0033 bool mark_missing_feds,
0034 const uint32_t errorThreshold)
0035 : headerBytes_(appended_bytes),
0036 fedBufferDumpFreq_(fed_buffer_dump_freq),
0037 fedEventDumpFreq_(fed_event_dump_freq),
0038 triggerFedId_(trigger_fed_id),
0039 useFedKey_(using_fed_key),
0040 unpackBadChannels_(unpack_bad_channels),
0041 markMissingFeds_(mark_missing_feds),
0042 event_(0),
0043 once_(true),
0044 first_(true),
0045 useDaqRegister_(false),
0046 quiet_(true),
0047 extractCm_(false),
0048 doFullCorruptBufferChecks_(false),
0049 doAPVEmulatorCheck_(true),
0050 errorThreshold_(errorThreshold),
0051 warnings_(sistrip::mlRawToDigi_, "[sistrip::RawToDigiUnpacker::createDigis]", edm::isDebugEnabled()) {
0052 if (edm::isDebugEnabled()) {
0053 LogTrace("SiStripRawToDigi") << "[sistrip::RawToDigiUnpacker::" << __func__ << "]"
0054 << " Constructing object...";
0055 }
0056 if (unpackBadChannels_) {
0057 edm::LogWarning("SiStripRawToDigi")
0058 << "Warning: Unpacking of bad channels enabled. Only enable this if you know what you are doing. "
0059 << std::endl;
0060 }
0061 }
0062
0063 RawToDigiUnpacker::~RawToDigiUnpacker() {
0064 if (edm::isDebugEnabled()) {
0065 LogTrace("SiStripRawToDigi") << "[sistrip::RawToDigiUnpacker::" << __func__ << "]"
0066 << " Destructing object...";
0067 }
0068 }
0069
0070 namespace {
0071
0072 edm::RunningAverage localRA(10000);
0073
0074 void maskFED(DetIdVector& maskedModules, SiStripFedCabling::ConnsConstIterRange fedConnections) {
0075 maskedModules.reserve(maskedModules.size() + fedConnections.size());
0076 for (const auto& conn : fedConnections) {
0077 if (conn.detId() && (conn.detId() != sistrip::invalid32_)) {
0078 maskedModules.push_back(conn.detId());
0079 }
0080 }
0081 }
0082 }
0083
0084 void RawToDigiUnpacker::createDigis(const SiStripFedCabling& cabling,
0085 const FEDRawDataCollection& buffers,
0086 SiStripEventSummary& summary,
0087 RawDigis& scope_mode,
0088 RawDigis& virgin_raw,
0089 RawDigis& proc_raw,
0090 Digis& zero_suppr,
0091 DetIdVector& detids,
0092 RawDigis& cm_values) {
0093
0094 assert(zs_work_digis_.empty());
0095 zs_work_digis_.reserve(localRA.upper());
0096
0097 detids.reserve(100);
0098
0099
0100 if (cabling.fedIds().empty()) {
0101 warnings_.add("No FEDs found in cabling map!");
0102 if (edm::isDebugEnabled()) {
0103
0104 std::vector<uint16_t> feds;
0105 for (uint16_t ifed = FEDNumbering::MINSiStripFEDID; ifed < FEDNumbering::MAXSiStripFEDID; ifed++) {
0106 if (ifed != triggerFedId_ && buffers.FEDData(static_cast<int>(ifed)).size()) {
0107 feds.push_back(ifed);
0108 }
0109 }
0110 LogTrace("SiStripRawToDigi") << "[sistrip::RawToDigiUnpacker::" << __func__ << "]"
0111 << " Found " << feds.size() << " FED buffers with non-zero size!";
0112 }
0113 }
0114
0115
0116 bool first_fed = true;
0117
0118
0119 std::vector<uint16_t>::const_iterator ifed = cabling.fedIds().begin();
0120 for (; ifed != cabling.fedIds().end(); ifed++) {
0121
0122 if (*ifed == triggerFedId_) {
0123 continue;
0124 }
0125
0126
0127 const FEDRawData& input = buffers.FEDData(static_cast<int>(*ifed));
0128
0129
0130 if (edm::isDebugEnabled()) {
0131 if (first_ && input.data()) {
0132 std::stringstream ss;
0133 ss << "[sistrip::RawToDigiUnpacker::" << __func__ << "]"
0134 << " Found FED id " << std::setw(4) << std::setfill(' ') << *ifed << " in FEDRawDataCollection"
0135 << " with non-zero pointer 0x" << std::hex << std::setw(8) << std::setfill('0')
0136 << reinterpret_cast<const uint32_t*>(input.data()) << std::dec << " and size " << std::setw(5)
0137 << std::setfill(' ') << input.size() << " chars";
0138 LogTrace("SiStripRawToDigi") << ss.str();
0139 }
0140 }
0141
0142
0143 if (edm::isDebugEnabled()) {
0144 if (fedBufferDumpFreq_ && !(event_ % fedBufferDumpFreq_)) {
0145 std::stringstream ss;
0146 dumpRawData(*ifed, input, ss);
0147 edm::LogVerbatim(sistrip::mlRawToDigi_) << ss.str();
0148 }
0149 }
0150
0151
0152 auto conns = cabling.fedConnections(*ifed);
0153
0154 const FEDBufferStatusCode st_buffer = preconstructCheckFEDBuffer(input);
0155
0156 if (FEDBufferStatusCode::SUCCESS != st_buffer) {
0157 if (FEDBufferStatusCode::BUFFER_NULL == st_buffer) {
0158 warnings_.add("NULL pointer to FEDRawData for FED", fmt::format("id {0}", *ifed));
0159 } else if (!input.size()) {
0160 warnings_.add("FEDRawData has zero size for FED", fmt::format("id {0}", *ifed));
0161 } else {
0162 warnings_.add("Exception caught when creating FEDBuffer object for FED",
0163 fmt::format("id {0}: {1}", *ifed, static_cast<int>(st_buffer)));
0164 }
0165
0166 maskFED(detids, conns);
0167 continue;
0168 }
0169 FEDBuffer buffer{input};
0170 const FEDBufferStatusCode st_chan = buffer.findChannels();
0171 if (FEDBufferStatusCode::SUCCESS != st_chan) {
0172 warnings_.add("Exception caught when creating FEDBuffer object for FED",
0173 fmt::format("id {0}: {1}", *ifed, static_cast<int>(st_chan)));
0174 maskFED(detids, conns);
0175 continue;
0176 }
0177 buffer.setLegacyMode(legacy_);
0178 if ((!buffer.doChecks(true)) && (!unpackBadChannels_ || !buffer.checkNoFEOverflows())) {
0179 warnings_.add("Exception caught when creating FEDBuffer object for FED",
0180 fmt::format("id {0}: FED Buffer check fails for FED ID {0}.", *ifed));
0181 maskFED(detids, conns);
0182 continue;
0183 }
0184 if (doFullCorruptBufferChecks_ && !buffer.doCorruptBufferChecks()) {
0185 warnings_.add("Exception caught when creating FEDBuffer object for FED",
0186 fmt::format("id {0}: FED corrupt buffer check fails for FED ID {0}.", *ifed));
0187 maskFED(detids, conns);
0188 continue;
0189 }
0190
0191
0192 if (first_fed && useDaqRegister_) {
0193 updateEventSummary(buffer, summary);
0194 first_fed = false;
0195 }
0196
0197
0198 if (!quiet_ && !summary.isSet()) {
0199 warnings_.add(
0200 "EventSummary is not set correctly! Missing information from both \"trigger FED\" and \"DAQ registers\"!");
0201 }
0202
0203
0204 if (!summary.valid()) {
0205 if (edm::isDebugEnabled()) {
0206 LogTrace("SiStripRawToDigi") << "[sistrip::RawToDigiUnpacker::" << __func__ << "]"
0207 << " EventSummary is not valid: skipping...";
0208 }
0209 continue;
0210 }
0211
0212
0213 const sistrip::FEDReadoutMode mode = buffer.readoutMode();
0214 const sistrip::FEDLegacyReadoutMode lmode =
0215 (legacy_) ? buffer.legacyReadoutMode() : sistrip::READOUT_MODE_LEGACY_INVALID;
0216
0217
0218 const sistrip::RunType runType_ = summary.runType();
0219 if (runType_ == sistrip::APV_LATENCY || runType_ == sistrip::FINE_DELAY) {
0220 useFedKey_ = false;
0221 }
0222
0223
0224 if (edm::isDebugEnabled()) {
0225 if (fedEventDumpFreq_ && !(event_ % fedEventDumpFreq_)) {
0226 std::stringstream ss;
0227 buffer.dump(ss);
0228 edm::LogVerbatim(sistrip::mlRawToDigi_) << ss.str();
0229 }
0230 }
0231
0232
0233 std::vector<FedChannelConnection>::const_iterator iconn = conns.begin();
0234 for (; iconn != conns.end(); iconn++) {
0235
0236 uint16_t chan = iconn->fedCh();
0237
0238
0239 if (!iconn->isConnected()) {
0240 continue;
0241 }
0242
0243
0244 if (!useFedKey_ && (!iconn->detId() || iconn->detId() == sistrip::invalid32_)) {
0245 continue;
0246 }
0247
0248
0249 if (!buffer.channelGood(iconn->fedCh(), doAPVEmulatorCheck_)) {
0250 if (!unpackBadChannels_ || !(buffer.fePresent(iconn->fedCh() / FEDCH_PER_FEUNIT) &&
0251 buffer.feEnabled(iconn->fedCh() / FEDCH_PER_FEUNIT))) {
0252 detids.push_back(iconn->detId());
0253 continue;
0254 }
0255 }
0256
0257
0258 const uint32_t fed_key =
0259 (summary.runType() == sistrip::FED_CABLING)
0260 ? ((*ifed & sistrip::invalid_) << 16) | (chan & sistrip::invalid_)
0261 : ((iconn->fedId() & sistrip::invalid_) << 16) | (iconn->fedCh() & sistrip::invalid_);
0262
0263
0264 const uint32_t key = (useFedKey_ || (!legacy_ && mode == sistrip::READOUT_MODE_SCOPE) ||
0265 (legacy_ && lmode == sistrip::READOUT_MODE_LEGACY_SCOPE))
0266 ? fed_key
0267 : iconn->detId();
0268
0269
0270 const uint16_t ipair = (useFedKey_ || (!legacy_ && mode == sistrip::READOUT_MODE_SCOPE) ||
0271 (legacy_ && lmode == sistrip::READOUT_MODE_LEGACY_SCOPE))
0272 ? 0
0273 : iconn->apvPairNumber();
0274
0275 const auto& fedChannel = buffer.channel(iconn->fedCh());
0276
0277 #ifdef EDM_ML_DEBUG
0278 std::stringstream smode;
0279 if (!legacy_)
0280 smode << mode;
0281 else
0282 smode << lmode;
0283 LogDebug("SiStripRawToDigi") << "Unpacking FED " << *ifed << " channel " << iconn->fedCh()
0284 << ((!legacy_) ? " " : " legacy ") << "data in mode " << smode.str()
0285 << " for module " << iconn->detId() << " pair " << ipair;
0286 #endif
0287 if (fedchannelunpacker::isZeroSuppressed(mode, legacy_, lmode)) {
0288 Registry regItem(key, 0, zs_work_digis_.size(), 0);
0289 const auto isNonLite = fedchannelunpacker::isNonLiteZS(mode, legacy_, lmode);
0290 const uint8_t pCode = (isNonLite ? buffer.packetCode(legacy_, iconn->fedCh()) : 0);
0291 if (isNonLite)
0292 LogDebug("SiStripRawToDigi") << "Non-lite zero-suppressed mode. Packet code=0x" << std::hex
0293 << uint16_t(pCode) << std::dec;
0294 const auto st_ch = fedchannelunpacker::unpackZeroSuppressed(
0295 fedChannel, std::back_inserter(zs_work_digis_), ipair * 256, isNonLite, mode, legacy_, lmode, pCode);
0296 if (fedchannelunpacker::StatusCode::ZERO_PACKET_CODE == st_ch ||
0297 fedchannelunpacker::StatusCode::BAD_PACKET_CODE == st_ch) {
0298 warnings_.add(fmt::format("Invalid packet code {0:#x} for zero-suppressed data", uint16_t(pCode)),
0299 fmt::format("FED {0} channel {1}", *ifed, iconn->fedCh()));
0300 } else if (fedchannelunpacker::StatusCode::SUCCESS != st_ch) {
0301 warnings_.add("Clusters are not ordered",
0302 fmt::format("FED {0} channel {1}: {2}", *ifed, iconn->fedCh(), toString(st_ch)));
0303 detids.push_back(iconn->detId());
0304 continue;
0305 }
0306 if (regItem.index != zs_work_digis_.size()) {
0307 regItem.length = zs_work_digis_.size() - regItem.index;
0308 regItem.first = zs_work_digis_[regItem.index].strip();
0309 zs_work_registry_.push_back(regItem);
0310 }
0311
0312 if (isNonLite && extractCm_) {
0313 if ((pCode == PACKET_CODE_ZERO_SUPPRESSED) || (pCode == PACKET_CODE_ZERO_SUPPRESSED10) ||
0314 (pCode == PACKET_CODE_ZERO_SUPPRESSED8_BOTBOT) || (pCode == PACKET_CODE_ZERO_SUPPRESSED8_TOPBOT)) {
0315 Registry regItem2(key, 2 * ipair, cm_work_digis_.size(), 2);
0316 cm_work_digis_.push_back(SiStripRawDigi(fedChannel.cmMedian(0)));
0317 cm_work_digis_.push_back(SiStripRawDigi(fedChannel.cmMedian(1)));
0318 cm_work_registry_.push_back(regItem2);
0319 } else {
0320 detids.push_back(iconn->detId());
0321 warnings_.add("Problem extracting common modes",
0322 fmt::format("FED {0} channel {1}:\n Request for CM median from channel with non-ZS "
0323 "packet code. Packet code is {2}.",
0324 *ifed,
0325 iconn->fedCh(),
0326 pCode));
0327 }
0328 }
0329 } else {
0330 auto st_ch = fedchannelunpacker::StatusCode::SUCCESS;
0331 if (fedchannelunpacker::isVirginRaw(mode, legacy_, lmode)) {
0332 Registry regItem(key, 256 * ipair, virgin_work_digis_.size(), 0);
0333 LogDebug("SiStripRawToDigi") << "Virgin raw packet code: 0x" << std::hex
0334 << uint16_t(buffer.packetCode(legacy_)) << " 0x"
0335 << uint16_t(fedChannel.packetCode()) << std::dec;
0336 st_ch = fedchannelunpacker::unpackVirginRaw(
0337 fedChannel, std::back_inserter(virgin_work_digis_), buffer.packetCode(legacy_));
0338 if (regItem.index != virgin_work_digis_.size()) {
0339 regItem.length = virgin_work_digis_.size() - regItem.index;
0340 virgin_work_registry_.push_back(regItem);
0341 }
0342 } else if (fedchannelunpacker::isProcessedRaw(mode, legacy_, lmode)) {
0343 Registry regItem(key, 256 * ipair, proc_work_digis_.size(), 0);
0344 st_ch = fedchannelunpacker::unpackProcessedRaw(fedChannel, std::back_inserter(proc_work_digis_));
0345 if (regItem.index != proc_work_digis_.size()) {
0346 regItem.length = proc_work_digis_.size() - regItem.index;
0347 proc_work_registry_.push_back(regItem);
0348 }
0349 } else if (fedchannelunpacker::isScopeMode(mode, legacy_, lmode)) {
0350 Registry regItem(key, 0, scope_work_digis_.size(), 0);
0351 st_ch = fedchannelunpacker::unpackScope(fedChannel, std::back_inserter(scope_work_digis_));
0352 if (regItem.index != scope_work_digis_.size()) {
0353 regItem.length = scope_work_digis_.size() - regItem.index;
0354 scope_work_registry_.push_back(regItem);
0355 }
0356 } else {
0357 warnings_.add(fmt::format("Unknown FED readout mode ({0})! Assuming SCOPE MODE...", int(mode)));
0358 Registry regItem(key, 0, scope_work_digis_.size(), 0);
0359 st_ch = fedchannelunpacker::unpackScope(fedChannel, std::back_inserter(scope_work_digis_));
0360 if (regItem.index != scope_work_digis_.size()) {
0361 regItem.length = scope_work_digis_.size() - regItem.index;
0362 scope_work_registry_.push_back(regItem);
0363 if (edm::isDebugEnabled()) {
0364 std::stringstream ss;
0365 ss << "Extracted " << regItem.length
0366 << " SCOPE MODE digis (samples[0] = " << scope_work_digis_[regItem.index] << ") from FED id/ch "
0367 << iconn->fedId() << "/" << iconn->fedCh();
0368 LogTrace("SiStripRawToDigi") << ss.str();
0369 }
0370 } else {
0371 warnings_.add("No SM digis found!");
0372 }
0373 }
0374 if (fedchannelunpacker::StatusCode::SUCCESS != st_ch) {
0375 warnings_.add(toString(st_ch), fmt::format("FED {0} channel {1}:", *ifed, iconn->fedCh()));
0376 }
0377 }
0378 }
0379 }
0380
0381
0382 unsigned int detIdsSize = detids.size();
0383 if (edm::isDebugEnabled() && detIdsSize) {
0384 std::ostringstream ss;
0385 ss << "[sistrip::RawToDigiUnpacker::" << __func__ << "]"
0386 << " Problems were found in data and " << detIdsSize << " channels could not be unpacked. "
0387 << "See output of FED Hardware monitoring for more information. ";
0388 edm::LogWarning(sistrip::mlRawToDigi_) << ss.str();
0389 }
0390 if ((errorThreshold_ != 0) && (detIdsSize > errorThreshold_)) {
0391 edm::LogError("TooManyErrors") << "Total number of errors = " << detIdsSize;
0392 }
0393
0394
0395 update(scope_mode, virgin_raw, proc_raw, zero_suppr, cm_values);
0396
0397
0398 event_++;
0399
0400
0401 if (first_) {
0402 first_ = false;
0403 }
0404
0405
0406 cleanupWorkVectors();
0407 }
0408
0409 void RawToDigiUnpacker::update(
0410 RawDigis& scope_mode, RawDigis& virgin_raw, RawDigis& proc_raw, Digis& zero_suppr, RawDigis& common_mode) {
0411 if (!zs_work_registry_.empty()) {
0412 std::sort(zs_work_registry_.begin(), zs_work_registry_.end());
0413 std::vector<edm::DetSet<SiStripDigi> > sorted_and_merged;
0414 sorted_and_merged.reserve(std::min(zs_work_registry_.size(), size_t(17000)));
0415
0416 bool errorInData = false;
0417 std::vector<Registry>::iterator it = zs_work_registry_.begin(), it2 = it + 1, end = zs_work_registry_.end();
0418 while (it < end) {
0419 sorted_and_merged.push_back(edm::DetSet<SiStripDigi>(it->detid));
0420 std::vector<SiStripDigi>& digis = sorted_and_merged.back().data;
0421
0422 size_t len = it->length;
0423 for (it2 = it + 1; (it2 != end) && (it2->detid == it->detid); ++it2) {
0424 len += it2->length;
0425 }
0426
0427 digis.reserve(len);
0428
0429 for (it2 = it + 0; (it2 != end) && (it2->detid == it->detid); ++it2) {
0430 digis.insert(digis.end(), &zs_work_digis_[it2->index], &zs_work_digis_[it2->index + it2->length]);
0431 }
0432 it = it2;
0433 }
0434
0435
0436 if (!__gnu_cxx::is_sorted(sorted_and_merged.begin(), sorted_and_merged.end())) {
0437
0438 throw cms::Exception("Bug Found")
0439 << "Container must be already sorted!\nat " << __FILE__ << ", line " << __LINE__ << "\n";
0440 }
0441
0442 std::vector<edm::DetSet<SiStripDigi> >::iterator iii = sorted_and_merged.begin();
0443 std::vector<edm::DetSet<SiStripDigi> >::iterator jjj = sorted_and_merged.end();
0444 for (; iii != jjj; ++iii) {
0445 if (!__gnu_cxx::is_sorted(iii->begin(), iii->end())) {
0446
0447 iii->clear();
0448 errorInData = true;
0449 }
0450 }
0451
0452
0453 if (errorInData)
0454 edm::LogWarning("CorruptData")
0455 << "Some modules contained corrupted ZS raw data, and have been skipped in unpacking\n";
0456
0457
0458 edm::DetSetVector<SiStripDigi> zero_suppr_dsv(sorted_and_merged, true);
0459 zero_suppr.swap(zero_suppr_dsv);
0460 }
0461
0462
0463 if (!virgin_work_registry_.empty()) {
0464 std::sort(virgin_work_registry_.begin(), virgin_work_registry_.end());
0465
0466 std::vector<edm::DetSet<SiStripRawDigi> > sorted_and_merged;
0467 sorted_and_merged.reserve(std::min(virgin_work_registry_.size(), size_t(17000)));
0468
0469 bool errorInData = false;
0470 std::vector<Registry>::iterator it = virgin_work_registry_.begin(), it2, end = virgin_work_registry_.end();
0471 while (it < end) {
0472 sorted_and_merged.push_back(edm::DetSet<SiStripRawDigi>(it->detid));
0473 std::vector<SiStripRawDigi>& digis = sorted_and_merged.back().data;
0474
0475 bool isDetOk = true;
0476
0477 int maxFirstStrip = it->first;
0478 for (it2 = it + 1; (it2 != end) && (it2->detid == it->detid); ++it2) {
0479
0480 if (it2->first <= maxFirstStrip) {
0481 isDetOk = false;
0482 continue;
0483 }
0484 maxFirstStrip = it2->first;
0485 }
0486 if (!isDetOk) {
0487 errorInData = true;
0488 it = it2;
0489 continue;
0490 }
0491
0492
0493 digis.resize(maxFirstStrip + 256);
0494
0495 for (it2 = it + 0; (it2 != end) && (it2->detid == it->detid); ++it2) {
0496
0497 if (it->length != 256) {
0498 isDetOk = false;
0499 continue;
0500 }
0501 std::copy(&virgin_work_digis_[it2->index], &virgin_work_digis_[it2->index + it2->length], &digis[it2->first]);
0502 }
0503 if (!isDetOk) {
0504 errorInData = true;
0505 digis.clear();
0506 it = it2;
0507 continue;
0508 }
0509 it = it2;
0510 }
0511
0512
0513 if (errorInData)
0514 edm::LogWarning("CorruptData")
0515 << "Some modules contained corrupted virgin raw data, and have been skipped in unpacking\n";
0516
0517
0518 if (!__gnu_cxx::is_sorted(sorted_and_merged.begin(), sorted_and_merged.end())) {
0519
0520 throw cms::Exception("Bug Found")
0521 << "Container must be already sorted!\nat " << __FILE__ << ", line " << __LINE__ << "\n";
0522 }
0523
0524
0525 edm::DetSetVector<SiStripRawDigi> virgin_raw_dsv(sorted_and_merged, true);
0526 virgin_raw.swap(virgin_raw_dsv);
0527 }
0528
0529
0530 if (!proc_work_registry_.empty()) {
0531 std::sort(proc_work_registry_.begin(), proc_work_registry_.end());
0532
0533 std::vector<edm::DetSet<SiStripRawDigi> > sorted_and_merged;
0534 sorted_and_merged.reserve(std::min(proc_work_registry_.size(), size_t(17000)));
0535
0536 bool errorInData = false;
0537 std::vector<Registry>::iterator it = proc_work_registry_.begin(), it2, end = proc_work_registry_.end();
0538 while (it < end) {
0539 sorted_and_merged.push_back(edm::DetSet<SiStripRawDigi>(it->detid));
0540 std::vector<SiStripRawDigi>& digis = sorted_and_merged.back().data;
0541
0542 bool isDetOk = true;
0543
0544 int maxFirstStrip = it->first;
0545 for (it2 = it + 1; (it2 != end) && (it2->detid == it->detid); ++it2) {
0546
0547 if (it2->first <= maxFirstStrip) {
0548 isDetOk = false;
0549 continue;
0550 }
0551 maxFirstStrip = it2->first;
0552 }
0553
0554 if (!isDetOk) {
0555 errorInData = true;
0556 it = it2;
0557 continue;
0558 }
0559
0560
0561 digis.resize(maxFirstStrip + 256);
0562
0563 for (it2 = it + 0; (it2 != end) && (it2->detid == it->detid); ++it2) {
0564
0565 if (it->length != 256) {
0566 isDetOk = false;
0567 continue;
0568 }
0569 std::copy(&proc_work_digis_[it2->index], &proc_work_digis_[it2->index + it2->length], &digis[it2->first]);
0570 }
0571
0572 if (!isDetOk) {
0573 errorInData = true;
0574 digis.clear();
0575 it = it2;
0576 continue;
0577 }
0578 it = it2;
0579 }
0580
0581
0582 if (errorInData)
0583 edm::LogWarning("CorruptData")
0584 << "Some modules contained corrupted proc raw data, and have been skipped in unpacking\n";
0585
0586
0587 if (!__gnu_cxx::is_sorted(sorted_and_merged.begin(), sorted_and_merged.end())) {
0588
0589 throw cms::Exception("Bug Found")
0590 << "Container must be already sorted!\nat " << __FILE__ << ", line " << __LINE__ << "\n";
0591 }
0592
0593
0594 edm::DetSetVector<SiStripRawDigi> proc_raw_dsv(sorted_and_merged, true);
0595 proc_raw.swap(proc_raw_dsv);
0596 }
0597
0598
0599 if (!scope_work_registry_.empty()) {
0600 std::sort(scope_work_registry_.begin(), scope_work_registry_.end());
0601
0602 std::vector<edm::DetSet<SiStripRawDigi> > sorted_and_merged;
0603 sorted_and_merged.reserve(scope_work_registry_.size());
0604
0605 bool errorInData = false;
0606 std::vector<Registry>::iterator it, end;
0607 for (it = scope_work_registry_.begin(), end = scope_work_registry_.end(); it != end; ++it) {
0608 sorted_and_merged.push_back(edm::DetSet<SiStripRawDigi>(it->detid));
0609 std::vector<SiStripRawDigi>& digis = sorted_and_merged.back().data;
0610 digis.insert(digis.end(), &scope_work_digis_[it->index], &scope_work_digis_[it->index + it->length]);
0611
0612 if ((it + 1 != end) && (it->detid == (it + 1)->detid)) {
0613 errorInData = true;
0614
0615 do {
0616 ++it;
0617 } while ((it + 1 != end) && (it->detid == (it + 1)->detid));
0618 }
0619 }
0620
0621
0622 if (errorInData)
0623 edm::LogWarning("CorruptData")
0624 << "Some fed keys contained corrupted scope mode data, and have been skipped in unpacking\n";
0625
0626
0627 if (!__gnu_cxx::is_sorted(sorted_and_merged.begin(), sorted_and_merged.end())) {
0628
0629 throw cms::Exception("Bug Found")
0630 << "Container must be already sorted!\nat " << __FILE__ << ", line " << __LINE__ << "\n";
0631 }
0632
0633
0634 edm::DetSetVector<SiStripRawDigi> scope_mode_dsv(sorted_and_merged, true);
0635 scope_mode.swap(scope_mode_dsv);
0636 }
0637
0638
0639 if (extractCm_) {
0640
0641 if (!cm_work_registry_.empty()) {
0642 std::sort(cm_work_registry_.begin(), cm_work_registry_.end());
0643
0644 std::vector<edm::DetSet<SiStripRawDigi> > sorted_and_merged;
0645 sorted_and_merged.reserve(std::min(cm_work_registry_.size(), size_t(17000)));
0646
0647 bool errorInData = false;
0648 std::vector<Registry>::iterator it = cm_work_registry_.begin(), it2, end = cm_work_registry_.end();
0649 while (it < end) {
0650 sorted_and_merged.push_back(edm::DetSet<SiStripRawDigi>(it->detid));
0651 std::vector<SiStripRawDigi>& digis = sorted_and_merged.back().data;
0652
0653 bool isDetOk = true;
0654
0655 int maxFirstStrip = it->first;
0656 for (it2 = it + 1; (it2 != end) && (it2->detid == it->detid); ++it2) {
0657
0658 if (it2->first <= maxFirstStrip) {
0659 isDetOk = false;
0660 continue;
0661 }
0662 maxFirstStrip = it2->first;
0663 }
0664 if (!isDetOk) {
0665 errorInData = true;
0666 it = it2;
0667 continue;
0668 }
0669
0670
0671 digis.resize(maxFirstStrip + 2);
0672
0673 for (it2 = it + 0; (it2 != end) && (it2->detid == it->detid); ++it2) {
0674
0675 if (it->length != 2) {
0676 isDetOk = false;
0677 continue;
0678 }
0679 std::copy(&cm_work_digis_[it2->index], &cm_work_digis_[it2->index + it2->length], &digis[it2->first]);
0680 }
0681 if (!isDetOk) {
0682 errorInData = true;
0683 digis.clear();
0684 it = it2;
0685 continue;
0686 }
0687 it = it2;
0688 }
0689
0690
0691 if (errorInData)
0692 edm::LogWarning("CorruptData")
0693 << "Some modules contained corrupted common mode data, and have been skipped in unpacking\n";
0694
0695
0696 if (!__gnu_cxx::is_sorted(sorted_and_merged.begin(), sorted_and_merged.end())) {
0697
0698 throw cms::Exception("Bug Found")
0699 << "Container must be already sorted!\nat " << __FILE__ << ", line " << __LINE__ << "\n";
0700 }
0701
0702
0703 edm::DetSetVector<SiStripRawDigi> common_mode_dsv(sorted_and_merged, true);
0704 common_mode.swap(common_mode_dsv);
0705 }
0706 }
0707 }
0708
0709 void RawToDigiUnpacker::cleanupWorkVectors() {
0710
0711
0712 localRA.update(zs_work_digis_.size());
0713 zs_work_registry_.clear();
0714 zs_work_digis_.clear();
0715 zs_work_digis_.shrink_to_fit();
0716 assert(zs_work_digis_.capacity() == 0);
0717 virgin_work_registry_.clear();
0718 virgin_work_digis_.clear();
0719 proc_work_registry_.clear();
0720 proc_work_digis_.clear();
0721 scope_work_registry_.clear();
0722 scope_work_digis_.clear();
0723 cm_work_registry_.clear();
0724 cm_work_digis_.clear();
0725 }
0726
0727 void RawToDigiUnpacker::triggerFed(const FEDRawDataCollection& buffers,
0728 SiStripEventSummary& summary,
0729 const uint32_t& event) {
0730
0731 const uint32_t* data_u32 = nullptr;
0732 uint32_t size_u32 = 0;
0733
0734
0735 if (triggerFedId_ < 0) {
0736 uint16_t ifed = 0;
0737 while (triggerFedId_ < 0 && ifed < 1 + FEDNumbering::lastFEDId()) {
0738 const FEDRawData& trigger_fed = buffers.FEDData(ifed);
0739 if (trigger_fed.data() && trigger_fed.size()) {
0740 const uint8_t* temp = trigger_fed.data();
0741 data_u32 = reinterpret_cast<const uint32_t*>(temp) + FEDHeader::length / sizeof(uint32_t) + 1;
0742 size_u32 = trigger_fed.size() / sizeof(uint32_t) - FEDHeader::length / sizeof(uint32_t) - 1;
0743 const FEDTrailer fedTrailer(temp + trigger_fed.size() - FEDTrailer::length);
0744 if (fedTrailer.conscheck() == 0xDEADFACE) {
0745 triggerFedId_ = ifed;
0746 if (edm::isDebugEnabled()) {
0747 std::stringstream ss;
0748 ss << "[sistrip::RawToDigiUnpacker::" << __func__ << "]"
0749 << " Search mode for 'trigger FED' activated!"
0750 << " Found 'trigger FED' info with id " << triggerFedId_;
0751 LogTrace("SiStripRawToDigi") << ss.str();
0752 }
0753 }
0754 }
0755 ifed++;
0756 }
0757 if (triggerFedId_ < 0) {
0758 triggerFedId_ = 0;
0759 if (edm::isDebugEnabled()) {
0760 std::stringstream ss;
0761 ss << "[sistrip::RawToDigiUnpacker::" << __func__ << "]"
0762 << " Search mode for 'trigger FED' activated!"
0763 << " 'Trigger FED' info not found!";
0764 edm::LogWarning(sistrip::mlRawToDigi_) << ss.str();
0765 }
0766 }
0767 }
0768
0769
0770 else if (triggerFedId_ > 0) {
0771 const FEDRawData& trigger_fed = buffers.FEDData(triggerFedId_);
0772 if (trigger_fed.data() && trigger_fed.size()) {
0773 const uint8_t* temp = trigger_fed.data();
0774 data_u32 = reinterpret_cast<const uint32_t*>(temp) + FEDHeader::length / sizeof(uint32_t) + 1;
0775 size_u32 = trigger_fed.size() / sizeof(uint32_t) - FEDHeader::length / sizeof(uint32_t) - 1;
0776 const FEDTrailer fedTrailer(temp + trigger_fed.size() - FEDTrailer::length);
0777 if (fedTrailer.conscheck() != 0xDEADFACE) {
0778 if (edm::isDebugEnabled()) {
0779 edm::LogWarning(sistrip::mlRawToDigi_) << "[sistrip::RawToDigiUnpacker::" << __func__ << "]"
0780 << " Unexpected stamp found in DAQ trailer (ie, not 0xDEADFACE)!"
0781 << " Buffer appears not to contain 'trigger FED' data!";
0782 }
0783 triggerFedId_ = 0;
0784 }
0785 }
0786
0787 } else {
0788 triggerFedId_ = 0;
0789 data_u32 = nullptr;
0790 size_u32 = 0;
0791 }
0792
0793
0794 if (triggerFedId_ > 0) {
0795
0796 if (!data_u32) {
0797 if (edm::isDebugEnabled()) {
0798 std::stringstream ss;
0799 ss << "[sistrip::RawToDigiUnpacker::" << __func__ << "]"
0800 << " NULL pointer to 'trigger FED' data";
0801 edm::LogWarning(sistrip::mlRawToDigi_) << ss.str();
0802 }
0803 return;
0804 }
0805 if (size_u32 < sizeof(TFHeaderDescription) / sizeof(uint32_t)) {
0806 if (edm::isDebugEnabled()) {
0807 std::stringstream ss;
0808 ss << "[sistrip::RawToDigiUnpacker::" << __func__ << "]"
0809 << " Unexpected 'Trigger FED' data size [32-bit words]: " << size_u32;
0810 edm::LogWarning(sistrip::mlRawToDigi_) << ss.str();
0811 }
0812 return;
0813 }
0814
0815
0816 const TFHeaderDescription* header = (const TFHeaderDescription*)data_u32;
0817 summary.event(static_cast<uint32_t>(header->getFedEventNumber()));
0818 summary.bx(static_cast<uint32_t>(header->getBunchCrossing()));
0819
0820
0821 uint32_t hsize = sizeof(TFHeaderDescription) / sizeof(uint32_t);
0822 const uint32_t* head = &data_u32[hsize];
0823 summary.commissioningInfo(head, event);
0824 summary.triggerFed(triggerFedId_);
0825 }
0826
0827
0828 if (summary.isSet() && once_) {
0829 if (edm::isDebugEnabled()) {
0830 std::stringstream ss;
0831 ss << "[sistrip::RawToDigiUnpacker::" << __func__ << "]"
0832 << " EventSummary built from \"trigger FED\":" << std::endl
0833 << summary;
0834 LogTrace("SiStripRawToDigi") << ss.str();
0835 }
0836 once_ = false;
0837 }
0838 }
0839
0840 void RawToDigiUnpacker::locateStartOfFedBuffer(const uint16_t& fed_id, const FEDRawData& input, FEDRawData& output) {
0841
0842 if (input.size() < 24) {
0843 output.resize(input.size());
0844 memcpy(output.data(), input.data(), input.size());
0845 if (edm::isDebugEnabled()) {
0846 std::stringstream ss;
0847 ss << "[sistrip::RawToDigiUnpacker::" << __func__ << "] "
0848 << "Input FEDRawData with FED id " << fed_id << " has size " << input.size();
0849 edm::LogWarning(sistrip::mlRawToDigi_) << ss.str();
0850 }
0851 return;
0852 }
0853
0854
0855 bool found = false;
0856 uint16_t ichar = 0;
0857 while (ichar < input.size() - 16 && !found) {
0858 uint16_t offset =
0859 headerBytes_ < 0 ? ichar : headerBytes_;
0860 const uint32_t* input_u32 = reinterpret_cast<const uint32_t*>(input.data() + offset);
0861 const uint32_t* fed_trailer = reinterpret_cast<const uint32_t*>(input.data() + input.size() - 8);
0862
0863
0864
0865 bool old_vme_header = (input_u32[0] & 0xF0000000) == 0x50000000 && (fed_trailer[0] & 0xF0000000) == 0xA0000000 &&
0866 ((fed_trailer[0] & 0x00FFFFFF) * 0x8) == (input.size() - offset);
0867
0868 bool old_slink_header = (input_u32[1] & 0xF0000000) == 0x50000000 &&
0869 (fed_trailer[1] & 0xF0000000) == 0xA0000000 &&
0870 ((fed_trailer[1] & 0x00FFFFFF) * 0x8) == (input.size() - offset);
0871
0872 bool old_slink_payload = (input_u32[3] & 0xFF000000) == 0xED000000;
0873
0874 bool new_buffer_format = (input_u32[2] & 0xFF000000) == 0xC5000000;
0875
0876 if (old_vme_header) {
0877
0878 found = true;
0879 output.resize(input.size() - offset);
0880 memcpy(output.data(),
0881 input.data() + offset,
0882 input.size() - offset);
0883 if (headerBytes_ < 0) {
0884 if (edm::isDebugEnabled()) {
0885 std::stringstream ss;
0886 ss << "[sistrip::RawToDigiUnpacker::" << __func__ << "]"
0887 << " Buffer for FED id " << fed_id << " has been found at byte position " << offset << " with a size of "
0888 << input.size() - offset << " bytes."
0889 << " Adjust the configurable 'AppendedBytes' to " << offset;
0890 LogTrace("SiStripRawToDigi") << ss.str();
0891 }
0892 }
0893
0894 } else if (old_slink_header) {
0895 if (old_slink_payload) {
0896
0897 found = true;
0898 output.resize(input.size() - offset);
0899 uint32_t* output_u32 = reinterpret_cast<uint32_t*>(output.data());
0900 uint16_t iter = offset;
0901 while (iter < output.size() / sizeof(uint32_t)) {
0902 output_u32[iter] = input_u32[iter + 1];
0903 output_u32[iter + 1] = input_u32[iter];
0904 iter += 2;
0905 }
0906 if (headerBytes_ < 0) {
0907 if (edm::isDebugEnabled()) {
0908 std::stringstream ss;
0909 ss << "[sistrip::RawToDigiUnpacker::" << __func__ << "]"
0910 << " Buffer (with MSB and LSB 32-bit words swapped) for FED id " << fed_id
0911 << " has been found at byte position " << offset << " with a size of " << output.size() << " bytes."
0912 << " Adjust the configurable 'AppendedBytes' to " << offset;
0913 LogTrace("SiStripRawToDigi") << ss.str();
0914 }
0915 }
0916
0917 } else if (new_buffer_format) {
0918
0919 found = true;
0920 output.resize(input.size() - offset);
0921 memcpy(output.data(),
0922 input.data() + offset,
0923 input.size() - offset);
0924 if (headerBytes_ < 0) {
0925 if (edm::isDebugEnabled()) {
0926 std::stringstream ss;
0927 ss << "[sistrip::RawToDigiUnpacker::" << __func__ << "]"
0928 << " Buffer for FED id " << fed_id << " has been found at byte position " << offset
0929 << " with a size of " << input.size() - offset << " bytes."
0930 << " Adjust the configurable 'AppendedBytes' to " << offset;
0931 LogTrace("SiStripRawToDigi") << ss.str();
0932 }
0933 }
0934
0935 } else {
0936 headerBytes_ < 0 ? found = false : found = true;
0937 }
0938 } else {
0939 headerBytes_ < 0 ? found = false : found = true;
0940 }
0941 ichar++;
0942 }
0943
0944
0945 if (output.size() == 0) {
0946
0947 output.resize(0);
0948 memcpy(output.data(), input.data(), 0);
0949 if (edm::isDebugEnabled()) {
0950 std::stringstream ss;
0951 if (headerBytes_ < 0) {
0952 ss << "[sistrip::RawToDigiUnpacker::" << __func__ << "]"
0953 << " DAQ header not found within buffer for FED id: " << fed_id;
0954 } else {
0955 const uint32_t* input_u32 = reinterpret_cast<const uint32_t*>(input.data());
0956 ss << "[sistrip::RawToDigiUnpacker::" << __func__ << "]"
0957 << " DAQ header not found at expected location for FED id: " << fed_id << std::endl
0958 << " First 64-bit word of buffer is 0x" << std::hex << std::setfill('0') << std::setw(8) << input_u32[0]
0959 << std::setfill('0') << std::setw(8) << input_u32[1] << std::dec << std::endl
0960 << " Adjust 'AppendedBytes' configurable to '-1' to activate 'search mode'";
0961 }
0962 edm::LogWarning(sistrip::mlRawToDigi_) << ss.str();
0963 }
0964
0965 } else if (output.size() < 24) {
0966
0967 if (edm::isDebugEnabled()) {
0968 std::stringstream ss;
0969 ss << "[sistrip::RawToDigiUnpacker::" << __func__ << "]"
0970 << " Unexpected buffer size! FEDRawData with FED id " << fed_id << " has size " << output.size();
0971 edm::LogWarning(sistrip::mlRawToDigi_) << ss.str();
0972 }
0973 }
0974 }
0975
0976 void RawToDigiUnpacker::updateEventSummary(const sistrip::FEDBuffer& fed, SiStripEventSummary& summary) {
0977 summary.event(fed.daqHeader().l1ID());
0978 summary.bx(fed.daqHeader().bxID());
0979
0980
0981
0982 sistrip::FEDDAQEventType readout_mode = fed.daqEventType();
0983 uint32_t daq1 = sistrip::invalid32_;
0984 uint32_t daq2 = sistrip::invalid32_;
0985
0986 if (fed.headerType() == sistrip::HEADER_TYPE_FULL_DEBUG) {
0987 const sistrip::FEDFullDebugHeader* header = nullptr;
0988 header = dynamic_cast<const sistrip::FEDFullDebugHeader*>(fed.feHeader());
0989 daq1 = static_cast<uint32_t>(header->daqRegister());
0990 daq2 = static_cast<uint32_t>(header->daqRegister2());
0991 }
0992
0993
0994 if (daq1 != 0 && daq1 != sistrip::invalid32_) {
0995 summary.triggerFed(triggerFedId_);
0996 summary.fedReadoutMode(readout_mode);
0997 summary.commissioningInfo(daq1, daq2);
0998
0999 if (summary.isSet() && once_) {
1000 if (edm::isDebugEnabled()) {
1001 std::stringstream ss;
1002 ss << "[sistrip::RawToDigiUnpacker::" << __func__ << "]"
1003 << " EventSummary built from FED DAQ registers:" << std::endl
1004 << summary;
1005 LogTrace("SiStripRawToDigi") << ss.str();
1006 }
1007 once_ = false;
1008 }
1009 }
1010 }
1011
1012 void RawToDigiUnpacker::dumpRawData(uint16_t fed_id, const FEDRawData& buffer, std::stringstream& ss) {
1013 ss << "[sistrip::RawToDigiUnpacker::" << __func__ << "]"
1014 << " Dump of buffer for FED id " << fed_id << std::endl
1015 << " Buffer contains " << buffer.size() << " bytes (NB: payload is byte-swapped)" << std::endl;
1016
1017 if (false) {
1018 const uint32_t* buffer_u32 = reinterpret_cast<const uint32_t*>(buffer.data());
1019 unsigned int empty = 0;
1020
1021 ss << "Byte-> 4 5 6 7 0 1 2 3\n";
1022 for (uint32_t i = 0; i < buffer.size() / 8; i++) {
1023 unsigned int temp0 = buffer_u32[i * 2] & sistrip::invalid32_;
1024 unsigned int temp1 = buffer_u32[i * 2 + 1] & sistrip::invalid32_;
1025 if (!temp0 && !temp1) {
1026 empty++;
1027 } else {
1028 if (empty) {
1029 ss << " [ empty words ]" << std::endl;
1030 empty = 0;
1031 }
1032 ss << std::dec << std::setfill(' ') << std::setw(6) << i * 8 << ": " << std::hex << std::setfill('0')
1033 << std::setw(8) << temp0 << std::setfill('0') << std::setw(8) << temp1 << std::dec << std::endl;
1034 }
1035 }
1036
1037 } else {
1038 ss << " Byte | <---- Byte order ----< | Byte" << std::endl;
1039 ss << " cntr | 7 6 5 4 3 2 1 0 | cntr" << std::endl;
1040 for (uint32_t i = 0; i < buffer.size() / 8; i++) {
1041
1042 uint16_t tmp0 = buffer.data()[i * 8 + 0] & 0xFF;
1043 uint16_t tmp1 = buffer.data()[i * 8 + 1] & 0xFF;
1044 uint16_t tmp2 = buffer.data()[i * 8 + 2] & 0xFF;
1045 uint16_t tmp3 = buffer.data()[i * 8 + 3] & 0xFF;
1046 uint16_t tmp4 = buffer.data()[i * 8 + 4] & 0xFF;
1047 uint16_t tmp5 = buffer.data()[i * 8 + 5] & 0xFF;
1048 uint16_t tmp6 = buffer.data()[i * 8 + 6] & 0xFF;
1049 uint16_t tmp7 = buffer.data()[i * 8 + 7] & 0xFF;
1050
1051
1052
1053
1054
1055
1056
1057
1058
1059 ss << std::dec << std::setfill(' ') << std::setw(6) << i * 8 + 7 << " : " << std::hex << std::setfill('0')
1060 << std::setw(2) << tmp7 << " " << std::setfill('0') << std::setw(2) << tmp6 << " " << std::setfill('0')
1061 << std::setw(2) << tmp5 << " " << std::setfill('0') << std::setw(2) << tmp4 << " " << std::setfill('0')
1062 << std::setw(2) << tmp3 << " " << std::setfill('0') << std::setw(2) << tmp2 << " " << std::setfill('0')
1063 << std::setw(2) << tmp1 << " " << std::setfill('0') << std::setw(2) << tmp0 << std::dec << " :"
1064 << std::setfill(' ') << std::setw(6) << i * 8 << std::endl;
1065
1066 }
1067 }
1068 ss << "[sistrip::RawToDigiUnpacker::" << __func__ << "]"
1069 << " End of FED buffer";
1070 }
1071 }
1072
1073
1074
1075
1076
1077
1078
1079
1080
1081
1082
1083
1084
1085
1086
1087
1088
1089
1090
1091
1092
1093
1094
1095
1096
1097
1098
1099
1100
1101
1102
1103
1104
1105
1106
1107
1108
1109
1110
1111
1112
1113