Back to home page

Project CMSSW displayed by LXR

 
 

    


File indexing completed on 2024-04-06 12:11:03

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());  //@@ Possible multiple entries (ok for Giovanni)
0079         }
0080       }
0081     }
0082   }  // namespace
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     // Clear done at the end
0094     assert(zs_work_digis_.empty());
0095     zs_work_digis_.reserve(localRA.upper());
0096     // Reserve space in bad module list
0097     detids.reserve(100);
0098 
0099     // Check if FEDs found in cabling map and event data
0100     if (cabling.fedIds().empty()) {
0101       warnings_.add("No FEDs found in cabling map!");
0102       if (edm::isDebugEnabled()) {
0103         // Check which FED ids have non-zero size buffers
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     // Flag for EventSummary update using DAQ register
0116     bool first_fed = true;
0117 
0118     // Retrieve FED ids from cabling map and iterate through
0119     std::vector<uint16_t>::const_iterator ifed = cabling.fedIds().begin();
0120     for (; ifed != cabling.fedIds().end(); ifed++) {
0121       // ignore trigger FED
0122       if (*ifed == triggerFedId_) {
0123         continue;
0124       }
0125 
0126       // Retrieve FED raw data for given FED
0127       const FEDRawData& input = buffers.FEDData(static_cast<int>(*ifed));
0128 
0129       // Some debug on FED buffer size
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       // Dump of FEDRawData to stdout
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       // get the cabling connections for this FED
0152       auto conns = cabling.fedConnections(*ifed);
0153       // check FEDRawData pointer, size, and more
0154       const FEDBufferStatusCode st_buffer = preconstructCheckFEDBuffer(input);
0155       // construct FEDBuffer
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         // FED buffer is bad and should not be unpacked. Skip this FED and mark all modules as bad.
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       // Check if EventSummary ("trigger FED info") needs updating
0192       if (first_fed && useDaqRegister_) {
0193         updateEventSummary(buffer, summary);
0194         first_fed = false;
0195       }
0196 
0197       // Check to see if EventSummary info is set
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       // Check to see if event is to be analyzed according to EventSummary
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       /// extract readout mode
0213       const sistrip::FEDReadoutMode mode = buffer.readoutMode();
0214       const sistrip::FEDLegacyReadoutMode lmode =
0215           (legacy_) ? buffer.legacyReadoutMode() : sistrip::READOUT_MODE_LEGACY_INVALID;
0216 
0217       // Retrive run type
0218       const sistrip::RunType runType_ = summary.runType();
0219       if (runType_ == sistrip::APV_LATENCY || runType_ == sistrip::FINE_DELAY) {
0220         useFedKey_ = false;
0221       }
0222 
0223       // Dump of FED buffer
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       // Iterate through FED channels, extract payload and create Digis
0233       std::vector<FedChannelConnection>::const_iterator iconn = conns.begin();
0234       for (; iconn != conns.end(); iconn++) {
0235         /// FED channel
0236         uint16_t chan = iconn->fedCh();
0237 
0238         // Check if fed connection is valid
0239         if (!iconn->isConnected()) {
0240           continue;
0241         }
0242 
0243         // Check DetId is valid (if to be used as key)
0244         if (!useFedKey_ && (!iconn->detId() || iconn->detId() == sistrip::invalid32_)) {
0245           continue;
0246         }
0247 
0248         // Check FED channel
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());  //@@ Possible multiple entries (ok for Giovanni)
0253             continue;
0254           }
0255         }
0256 
0257         // Determine whether FED key is inferred from cabling or channel loop
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         // Determine whether DetId or FED key should be used to index digi containers
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         // Determine APV std::pair number (needed only when using DetId)
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());  //@@ Possible multiple entries (ok for Giovanni)
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           // Common mode values
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());  //@@ Possible multiple entries (ok for Giovanni)
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 {  // Unknown readout mode! => assume scope mode
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       }  // channel loop
0379     }    // fed loop
0380 
0381     // bad channels warning
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     // update DetSetVectors
0395     update(scope_mode, virgin_raw, proc_raw, zero_suppr, cm_values);
0396 
0397     // increment event counter
0398     event_++;
0399 
0400     // no longer first event!
0401     if (first_) {
0402       first_ = false;
0403     }
0404 
0405     // final cleanup, just in case
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         // first count how many digis we have
0422         size_t len = it->length;
0423         for (it2 = it + 1; (it2 != end) && (it2->detid == it->detid); ++it2) {
0424           len += it2->length;
0425         }
0426         // reserve memory
0427         digis.reserve(len);
0428         // push them in
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       // check sorting
0436       if (!__gnu_cxx::is_sorted(sorted_and_merged.begin(), sorted_and_merged.end())) {
0437         // this is an error in the code: i DID sort it already!
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           // this might be an error in the data, if the raws from one FED are not sorted
0447           iii->clear();
0448           errorInData = true;
0449         }
0450       }
0451 
0452       // output error
0453       if (errorInData)
0454         edm::LogWarning("CorruptData")
0455             << "Some modules contained corrupted ZS raw data, and have been skipped in unpacking\n";
0456 
0457       // make output DetSetVector
0458       edm::DetSetVector<SiStripDigi> zero_suppr_dsv(sorted_and_merged, true);
0459       zero_suppr.swap(zero_suppr_dsv);
0460     }
0461 
0462     // Populate final DetSetVector container with VR data
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         // first count how many digis we have
0477         int maxFirstStrip = it->first;
0478         for (it2 = it + 1; (it2 != end) && (it2->detid == it->detid); ++it2) {
0479           // duplicated APV or data corruption. DO NOT 'break' here!
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         }  // skip whole det
0491 
0492         // make room for 256 * (max_apv_pair + 1) Raw Digis
0493         digis.resize(maxFirstStrip + 256);
0494         // push them in
0495         for (it2 = it + 0; (it2 != end) && (it2->detid == it->detid); ++it2) {
0496           // data corruption. DO NOT 'break' here
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         }  // skip whole det
0509         it = it2;
0510       }
0511 
0512       // output error
0513       if (errorInData)
0514         edm::LogWarning("CorruptData")
0515             << "Some modules contained corrupted virgin raw data, and have been skipped in unpacking\n";
0516 
0517       // check sorting
0518       if (!__gnu_cxx::is_sorted(sorted_and_merged.begin(), sorted_and_merged.end())) {
0519         // this is an error in the code: i DID sort it already!
0520         throw cms::Exception("Bug Found")
0521             << "Container must be already sorted!\nat " << __FILE__ << ", line " << __LINE__ << "\n";
0522       }
0523 
0524       // make output DetSetVector
0525       edm::DetSetVector<SiStripRawDigi> virgin_raw_dsv(sorted_and_merged, true);
0526       virgin_raw.swap(virgin_raw_dsv);
0527     }
0528 
0529     // Populate final DetSetVector container with VR data
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         // first count how many digis we have
0544         int maxFirstStrip = it->first;
0545         for (it2 = it + 1; (it2 != end) && (it2->detid == it->detid); ++it2) {
0546           // duplicated APV or data corruption. DO NOT 'break' here!
0547           if (it2->first <= maxFirstStrip) {
0548             isDetOk = false;
0549             continue;
0550           }
0551           maxFirstStrip = it2->first;
0552         }
0553         // skip whole det
0554         if (!isDetOk) {
0555           errorInData = true;
0556           it = it2;
0557           continue;
0558         }
0559 
0560         // make room for 256 * (max_apv_pair + 1) Raw Digis
0561         digis.resize(maxFirstStrip + 256);
0562         // push them in
0563         for (it2 = it + 0; (it2 != end) && (it2->detid == it->detid); ++it2) {
0564           // data corruption. DO NOT 'break' here
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         // skip whole det
0572         if (!isDetOk) {
0573           errorInData = true;
0574           digis.clear();
0575           it = it2;
0576           continue;
0577         }
0578         it = it2;
0579       }
0580 
0581       // output error
0582       if (errorInData)
0583         edm::LogWarning("CorruptData")
0584             << "Some modules contained corrupted proc raw data, and have been skipped in unpacking\n";
0585 
0586       // check sorting
0587       if (!__gnu_cxx::is_sorted(sorted_and_merged.begin(), sorted_and_merged.end())) {
0588         // this is an error in the code: i DID sort it already!
0589         throw cms::Exception("Bug Found")
0590             << "Container must be already sorted!\nat " << __FILE__ << ", line " << __LINE__ << "\n";
0591       }
0592 
0593       // make output DetSetVector
0594       edm::DetSetVector<SiStripRawDigi> proc_raw_dsv(sorted_and_merged, true);
0595       proc_raw.swap(proc_raw_dsv);
0596     }
0597 
0598     // Populate final DetSetVector container with SM data
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           // let's skip *all* the detsets for that key, as we don't know which is the correct one!
0615           do {
0616             ++it;
0617           } while ((it + 1 != end) && (it->detid == (it + 1)->detid));
0618         }
0619       }
0620 
0621       // output error
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       // check sorting
0627       if (!__gnu_cxx::is_sorted(sorted_and_merged.begin(), sorted_and_merged.end())) {
0628         // this is an error in the code: i DID sort it already!
0629         throw cms::Exception("Bug Found")
0630             << "Container must be already sorted!\nat " << __FILE__ << ", line " << __LINE__ << "\n";
0631       }
0632 
0633       // make output DetSetVector
0634       edm::DetSetVector<SiStripRawDigi> scope_mode_dsv(sorted_and_merged, true);
0635       scope_mode.swap(scope_mode_dsv);
0636     }
0637 
0638     // Populate DetSetVector with Common Mode values
0639     if (extractCm_) {
0640       // Populate final DetSetVector container with VR data
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           // first count how many digis we have
0655           int maxFirstStrip = it->first;
0656           for (it2 = it + 1; (it2 != end) && (it2->detid == it->detid); ++it2) {
0657             // duplicated APV or data corruption. DO NOT 'break' here!
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           }  // skip whole det
0669 
0670           // make room for 2 * (max_apv_pair + 1) Common mode values
0671           digis.resize(maxFirstStrip + 2);
0672           // push them in
0673           for (it2 = it + 0; (it2 != end) && (it2->detid == it->detid); ++it2) {
0674             // data corruption. DO NOT 'break' here
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           }  // skip whole det
0687           it = it2;
0688         }
0689 
0690         // output error
0691         if (errorInData)
0692           edm::LogWarning("CorruptData")
0693               << "Some modules contained corrupted common mode data, and have been skipped in unpacking\n";
0694 
0695         // check sorting
0696         if (!__gnu_cxx::is_sorted(sorted_and_merged.begin(), sorted_and_merged.end())) {
0697           // this is an error in the code: i DID sort it already!
0698           throw cms::Exception("Bug Found")
0699               << "Container must be already sorted!\nat " << __FILE__ << ", line " << __LINE__ << "\n";
0700         }
0701 
0702         // make output DetSetVector
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     // Clear working areas and registries
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     // Pointer to data (recast as 32-bit words) and number of 32-bit words
0731     const uint32_t* data_u32 = nullptr;
0732     uint32_t size_u32 = 0;
0733 
0734     // Search mode
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     // "Trigger FED" id given in .cfg file
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     // Populate summary object with commissioning information
0794     if (triggerFedId_ > 0) {
0795       // Some checks
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       // Write event-specific data to event
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       // Write commissioning information to event
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     // Some debug
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     // Check size of input buffer
0842     if (input.size() < 24) {
0843       output.resize(input.size());  // Return UNadjusted buffer start position and 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     // Iterator through buffer to find DAQ header
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_;  // Negative value means use "search mode" to find DAQ header
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       // see info on FED 32-bit swapping at end-of-file
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         // Found DAQ header at byte position 'offset'
0878         found = true;
0879         output.resize(input.size() - offset);
0880         memcpy(output.data(),           // target
0881                input.data() + offset,   // source
0882                input.size() - offset);  // nbytes
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           // Found DAQ header (with MSB and LSB 32-bit words swapped) at byte position 'offset'
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           // Found DAQ header at byte position 'offset'
0919           found = true;
0920           output.resize(input.size() - offset);
0921           memcpy(output.data(),           // target
0922                  input.data() + offset,   // source
0923                  input.size() - offset);  // nbytes
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     // Check size of output buffer
0945     if (output.size() == 0) {
0946       // Did not find DAQ header after search => return buffer with null size
0947       output.resize(0);                        //@@ NULL SIZE
0948       memcpy(output.data(), input.data(), 0);  //@@ NULL SIZE
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) {  // Found DAQ header after search, but too few words
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     // Retrieve contents of DAQ registers
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     // If FED DAQ registers contain info, update (and possibly overwrite) EventSummary
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         //if ( i>=20 && ((i+4)<(buffer.size()/8)) ) { continue; }
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         //  if ( !tmp0 && !tmp1 && !tmp2 && !tmp3 &&
1051         //       !tmp4 && !tmp5 && !tmp6 && !tmp7 ) { empty++; }
1052         //  else {
1053         //    if ( empty ) {
1054         //      ss << "         [.."
1055         //         << std::dec << std::setfill('.') << std::setw(4) << empty
1056         //         << " null words....]" << std::endl;
1057         //      empty = 0;
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 }  // namespace sistrip
1072 
1073 /*
1074 
1075 Some info on FED buffer 32-bit word swapping.
1076 
1077 Table below indicates if data are swapped relative to the "old"
1078 VME format (as originally expected by the Fed9UEvent class).
1079 
1080 -------------------------------------------
1081 | SWAPPED?    |         DATA FORMAT       |
1082 | (wrt "OLD") | OLD (0xED)  | NEW (0xC5)  |
1083 |             | VME | SLINK | VME | SLINK |
1084 -------------------------------------------
1085 | DAQ HEADER  |  N  |   Y   |  Y  |   Y   |
1086 | TRK HEADER  |  N  |   Y   |  N  |   N   |
1087 | PAYLOAD     |  N  |   Y   |  N  |   N   |
1088 | DAQ TRAILER |  N  |   Y   |  Y  |   Y   |
1089 -------------------------------------------
1090 
1091 So, in code, we check in code order of bytes in DAQ header/trailer only:
1092 -> if "old_vme_header",           then old format read out via vme, so do nothing.
1093 -> else if "old_slink_header",    then data may be wrapped, so check additionally the TRK header:
1094 ---> if "old_slink_payload",       then old format read out via slink, so swap all data;
1095 ---> else if "new_buffer_format",  then new format, handled internally by Fed9UEvent, so do nothing.
1096 
1097 Pattern matching to find DAQ and tracker headers, and DAQ trailer:
1098 DAQ header,  4 bits, in field  |BOE_1|      with value 0x5
1099 DAQ trailer, 4 bits, in field  |EOE_1|      with value 0xA
1100 TRK header,  8 bits, in field  |Hdr format| with value 0xED or 0xC5
1101 
1102 -------------------------------------------------------------------------------------------
1103 | SWAPPED?    |                                 DATA FORMAT                               |
1104 | (wrt "OLD") |               OLD (0xED)            |               NEW (0xC5)            |
1105 |             |       VME        |      SLINK       |       VME        |      SLINK       |
1106 -------------------------------------------------------------------------------------------
1107 | DAQ HEADER  | ........5....... | 5............... | 5............... | 5............... |
1108 | TRK HEADER  | ........ED...... | ED.............. | ........C5...... | ........C5...... |
1109 | PAYLOAD     | ..........EA.... | ..EA............ | ..EA............ | ............EA.. |
1110 | DAQ TRAILER | ........A....... | A............... | A............... | A............... |
1111 -------------------------------------------------------------------------------------------
1112 
1113 */